Vorrei controllare ciò che è scritto in uno stream, ovvero coutper un oggetto di una classe personalizzata. È possibile in C ++? In Java è possibile ignorare il toString()metodo per scopi simili.
Vorrei controllare ciò che è scritto in uno stream, ovvero coutper un oggetto di una classe personalizzata. È possibile in C ++? In Java è possibile ignorare il toString()metodo per scopi simili.
Risposte:
In C ++ puoi sovraccaricare operator<<per ostreame la tua classe personalizzata:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
In questo modo puoi generare istanze della tua classe su stream:
A x = ...;
std::cout << x << std::endl;
Nel caso in cui operator<<desideri stampare interni di classe Ae abbia davvero bisogno dell'accesso ai suoi membri privati e protetti, puoi anche dichiararlo come funzione amico:
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 anche all'interno del corpo della classe - con quello, non dovrai fare using namespaceper lo spazio dei nomi che contiene l'operatore (e la classe), ma ADL lo troverà fintanto che l'oggetto di quella classe è uno degli operandi.
dumpmetodo pubblico è sporco e non necessario. Usare friendqui va benissimo. Se preferisci un metodo ridondante o invadente friendè una questione di gusti, sebbene friendsia stato probabilmente introdotto per questo preciso scopo.
operator<<()una funzione membro non funzionerà: dovresti renderlo una funzione membro std::ostreamaffinché accetti un operando di tipo sinistro std::ostream.
Puoi anche farlo in questo modo, consentendo il 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); }
toStringcomportamento di Java .
In C ++ 11, to_string viene infine aggiunto allo standard.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
ToString()è una funzione virtuale definita sulla classe base di tutti gli oggetti e viene quindi utilizzata come modo standard per esprimere una rappresentazione in forma di stringa di qualsiasi oggetto. Queste funzioni std::stringsi applicano solo ai tipi integrati. Il modo idiomatico in C ++ è di sovrascrivere l' <<operatore per tipi personalizzati.
operator<<, rispetto alla semplice Stringsemantica di Java, mi spinge a sottolineare che to_string()non è solo "un'utile aggiunta", ma il nuovo modo preferito di farlo in C ++. Se, come per l'OP, Asi desidera una rappresentazione di stringa personalizzata di una classe , basta scrivere una string to_string(A a)definizione di class Asuffissi di seguito. Questo si propaga con l'ereditarietà come in Java e può essere combinato (mediante aggiunta di stringhe) come in Java. Il non overriden toString()in Java ha comunque un uso limitato.
Come estensione a ciò che ha detto John, se vuoi estrarre la rappresentazione di stringa e archiviarla in std::stringquesto modo:
#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::stringstreamsi trova <sstream>nell'intestazione.
Alla domanda è stata data una risposta. Ma volevo aggiungere un esempio 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;
}
Questo esempio richiede la comprensione del sovraccarico dell'operatore.