Me gustaría controlar lo que está escrito en una secuencia, es decir cout, para un objeto de una clase personalizada. ¿Es eso posible en C ++? En Java, podría anular el toString()método para un propósito similar.
Me gustaría controlar lo que está escrito en una secuencia, es decir cout, para un objeto de una clase personalizada. ¿Es eso posible en C ++? En Java, podría anular el toString()método para un propósito similar.
Respuestas:
En C ++ se puede sobrecargar operator<<de ostreamy la clase personalizada:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
De esta manera, puede generar instancias de su clase en secuencias:
A x = ...;
std::cout << x << std::endl;
En caso de que operator<<desee imprimir elementos internos de la clase Ay realmente necesite acceso a sus miembros privados y protegidos, también puede declararlo como una función amiga:
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, y también dentro del cuerpo de la clase; con eso, no tendrá que hacer using namespacepara el espacio de nombres que contiene el operador (y la clase), pero ADL lo encontrará siempre que el objeto de esa clase sea Uno de los operandos.
dumpmétodo público es sucio e innecesario. Usar friendaquí está perfectamente bien. Si prefiere un método redundante o intrusivo friendes una cuestión de gustos, aunque friendpodría decirse que se ha introducido para este propósito exacto.
operator<<()una función miembro no funcionará: tendría que hacer que sea una función miembro std::ostreampara que acepte un operando de tipo izquierdo std::ostream.
También puede hacerlo de esta manera, permitiendo el 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); }
toStringcomportamiento de Java .
En C ++ 11, to_string finalmente se agrega al estándar.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
ToString()es una función virtual definida en la clase base de todos los objetos y, por lo tanto, se utiliza como una forma estándar para expresar una representación de cadena de cualquier objeto. Estas funciones std::stringsolo se aplican a los tipos integrados. La forma idiomática en C ++ es anular el <<operador para los tipos personalizados.
operator<<, en comparación con la Stringsemántica simple de Java, me lleva a comentar que to_string()no solo es "una adición útil", sino la nueva forma preferida de hacerlo en C ++. Si, como por el OP, Ase desea una representación de cadena personalizada de una clase , simplemente escribiendo una string to_string(A a)definición de class Asufijos a continuación. Esto se propaga con herencia como en Java, y se puede combinar (mediante la adición de cadenas) como en Java. No anulado toString()en Java es de uso limitado de todos modos.
Como una extensión de lo que dijo John, si desea extraer la representación de cadena y almacenarla, std::stringhaga lo siguiente:
#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::stringstreamse encuentra en el <sstream>encabezado.
La pregunta ha sido respondida. Pero quería agregar un ejemplo 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 ejemplo requiere comprender la sobrecarga del operador.