Como funcionam os fluxos de c++?

Gostava de saber como é que as aulas de stream funcionam em C++. Quando dizes:
cout<<"Hello\n";

o que faz exactamente"<<". Eu sei que cout é uma forma de objeto iostream que representa o fluxo de saída padrão orientado para caracteres estreitos (char).

Em C "<<" está o operador de shift bitwise por isso move bits para a esquerda, mas em C++ é e Operador de inserção. É tudo o que sei, não percebo como é que isto funciona debaixo do capô.

O que estou a pedir é detalhado. explicação sobre as classes stream em C++, como elas são definidas e implementadas.

Muito obrigado pelo seu tempo e desculpe pelo meu inglês.

Author: miguel, 2014-04-23

3 answers

Vamos criar uma classe que se pareça com cout (mas sem tantos sinos e assobios).
#include <string>

class os_t {
    public:
        os_t & operator<<(std::string const & s) {
            printf("%s", s.c_str());
            return *this;
        }
};

int main() {
    os_t os;

    os << "hello\n";
    os << "chaining " << "works too." << "\n";
}

Notas:

  • operator<< é uma sobrecarga do operador tal como operator+ ou todos os outros operadores.
  • acorrentar funciona porque nós mesmos voltamos: return *this;.
E se não conseguires mudar a aula porque outra pessoa a escreveu?

Não temos de usar funções de membro para definir esta funcionalidade. Também podemos usar funções livres. Deixa mostra isso também.

#include <string>

class os_t {
    public:
        os_t & operator<<(std::string const & s) {
            printf("%s", s.c_str());
            return *this;
        }
};

os_t & operator<<(os_t & os, int x) {
    printf("%d", x);
    return os;

    // We could also have used the class's functionality to do this:
    // os << std::to_string(x);
    // return os;
}

int main() {
    os_t os;

    os << "now we can also print integers: " << 3 << "\n";
}

Onde mais é que a sobrecarga do operador é útil?

Um grande exemplo de como este tipo de lógica é útil pode ser encontrado na biblioteca GMP. Esta biblioteca foi projetada para permitir números inteiros arbitrariamente grandes. Nós fazemos isso, usando uma classe personalizada. Aqui está um exemplo do seu uso. Note que o overloading do operador nos deixa escrever um código que parece quase idêntico se nós estávamos usando o tipo tradicional int.
#include <iostream>
#include <gmpxx.h>

int main() {
    mpz_class x("7612058254738945");
    mpz_class y("9263591128439081");

    x = x + y * y;
    y = x << 2;

    std::cout << x + y << std::endl;
}
 8
Author: Bill Lynch, 2014-04-23 20:32:43

<< é um operador binário em C++, e assim pode ser sobrecarregado.

Você conhece o uso C deste operador, onde 1 << 3 é uma operação binária retornando 8. Pode pensar nisto como o método int operator<<(int, int) onde passar nos argumentos 1 e 3 devolve 8.

Tecnicamente, operator<<podia fazer qualquer coisa. É um método arbitrário.

Por convenção em C++, o operador << é utilizado para o tratamento de fluxos, para além de ser o operador de mudança de bits. Quando você executa cout << "Hello!", você está chamando um método com protótipo ostream & operator<< (ostream & output, char const * stream_me). Note o valor de retorno ostream &. Esse retorno permite que você chame o método várias vezes, como std::cout << "Hello World" << "!"; que está chamando operator<< duas vezes... once on std:: cout and "Hello World", and the second time on the result of that first invocation and"!".

Em geral, se você criasse uma classe chamada class Foo, e quisesse que fosse impressa, você poderia definir o seu método de impressão como ostream & operator<< (ostream & output, Foo const & print_me). Aqui está um exemplo.

#include <iostream>

struct Circle {
  float x, y;
  float radius;
};

std::ostream & operator<< (std::ostream & output, Circle const & print_me) {
  output << "A circle at (" << print_me.x << ", " << print_me.y << ") with radius " << print_me.radius << ".";
}

int main (void) {
  Circle my_circle;
  my_circle.x = 5;
  my_circle.y = 10;
  my_circle.radius = 20;

  std::cout << my_circle << '\n';

  return 0;
}
 4
Author: QuestionC, 2014-04-23 19:56:11

Os operadores podem ser considerados funções com açúcar sintático que permitem uma sintaxe limpa. Este é apenas um caso de sobrecarga do operador.

 1
Author: Veritas, 2017-05-23 11:57:28