Eu gostaria de controlar o que é gravado em um fluxo, ou seja cout
, para um objeto de uma classe personalizada. Isso é possível em C ++? Em Java, você pode substituir o toString()
método para fins semelhantes.
Eu gostaria de controlar o que é gravado em um fluxo, ou seja cout
, para um objeto de uma classe personalizada. Isso é possível em C ++? Em Java, você pode substituir o toString()
método para fins semelhantes.
Respostas:
Em C ++, você pode sobrecarregar operator<<
para ostream
e sua classe personalizada:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
Dessa maneira, você pode gerar instâncias da sua classe nos fluxos:
A x = ...;
std::cout << x << std::endl;
Caso você operator<<
deseje imprimir páginas internas da classe A
e realmente precise acessar seus membros particulares e protegidos, você também pode declarar isso como uma função de amigo:
class A {
private:
friend std::ostream& operator<<(std::ostream&, const A&);
int j;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.j << ")";
}
friend
, e também dentro do corpo da classe - com isso, você não terá que fazer using namespace
pelo espaço para nome que contém o operador (e a classe), mas a ADL o achará enquanto o objeto dessa classe for um dos operandos.
dump
método público é sujo e desnecessário. Usar friend
aqui é perfeitamente bom. Se você prefere um método redundante ou um intrusivo, friend
é uma questão de gosto, embora friend
tenha sido discutido com esse objetivo exato.
operator<<()
uma função de membro não funcionará: você precisaria torná-la uma função de membro std::ostream
para aceitar um operando do tipo à esquerda std::ostream
.
Você também pode fazer dessa maneira, permitindo o polimorfismo:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
toString
comportamento do Java .
No C ++ 11, to_string é finalmente adicionado ao padrão.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
ToString()
é uma função virtual definida na classe base de todos os objetos e, portanto, é usada como uma maneira padrão de expressar uma representação de seqüência de caracteres de qualquer objeto. Essas funções se std::string
aplicam apenas a tipos internos. A maneira idiomática no C ++ é substituir o <<
operador por tipos personalizados.
operator<<
, em comparação com a simples String
semântica de Java, me leva a observar que isso to_string()
não é apenas "uma adição útil", mas a nova maneira preferida de fazê-lo em C ++. Se, como no OP, uma representação de string personalizada de uma classe A
for desejada, basta escrever uma string to_string(A a)
definição abaixo de class A
suficiente. Isso se propaga com herança como em Java e pode ser combinado (por adição de sequência) como em Java. De qualquer forma, o domínio não substituído toString()
em Java é de uso limitado.
Como uma extensão do que John disse, se você deseja extrair a representação de string e armazená-la, std::string
faça o seguinte:
#include <sstream>
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace
std::stringstream
está localizado no <sstream>
cabeçalho.
A pergunta foi respondida. Mas eu queria adicionar um exemplo concreto.
class Point{
public:
Point(int theX, int theY) :x(theX), y(theY)
{}
// Print the object
friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
int x;
int y;
};
ostream& operator <<(ostream& outputStream, const Point& p){
int posX = p.x;
int posY = p.y;
outputStream << "x="<<posX<<","<<"y="<<posY;
return outputStream;
}
Este exemplo requer a compreensão da sobrecarga do operador.