Я хотел бы контролировать то, что записывается в поток, т. Е. coutДля объекта пользовательского класса. Это возможно в C ++? В Java вы можете переопределить toString()метод для аналогичной цели.
Я хотел бы контролировать то, что записывается в поток, т. Е. coutДля объекта пользовательского класса. Это возможно в C ++? В Java вы можете переопределить toString()метод для аналогичной цели.
Ответы:
В C ++ можно перегрузить operator<<для ostreamи пользовательского класса:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
Таким образом, вы можете выводить экземпляры вашего класса на потоки:
A x = ...;
std::cout << x << std::endl;
Если вы operator<<хотите распечатать внутреннее содержимое класса Aи действительно нуждаетесь в доступе к его закрытым и защищенным членам, вы можете также объявить его как функцию друга:
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, а также внутри тела класса - при этом вам не придется делать это using namespaceдля пространства имен, содержащего оператор (и класс), но ADL найдет его, пока объект этого класса один из операндов.
dumpпубличный метод грязный и ненужный. Использование friendздесь прекрасно. Предпочитаете ли вы избыточный метод или навязчивый friend- это дело вкуса, хотя friend, возможно, оно было введено именно для этой цели.
operator<<()функции-члена не будет работать: вам придется сделать ее функцией-членом, std::ostreamчтобы она принимала левый операнд типа std::ostream.
Вы также можете сделать это таким образом, разрешив полиморфизм:
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поведение Java .
В C ++ 11 to_string наконец добавляется в стандарт.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
ToString()это виртуальная функция, определенная в базовом классе всех объектов, и поэтому она используется как стандартный способ выражения строкового представления любого объекта. Эти функции std::stringотносятся только к встроенным типам. Идиоматический способ в C ++ - переопределить <<оператор для пользовательских типов.
operator<<сравнению с простой Stringсемантикой Java заставляет меня заметить, что to_string()это не только «полезное дополнение», но и новый предпочтительный способ сделать это в C ++. Если, как и в случае с OP, Aжелательно пользовательское строковое представление класса , достаточно просто написать приведенное string to_string(A a)ниже определение class A. Это распространяется с наследованием, как в Java, и может быть объединено (путем добавления строки), как в Java. Не переопределенный toString()в Java в любом случае имеет ограниченное использование.
В качестве дополнения к тому, что сказал Джон, если вы хотите извлечь строковое представление и сохранить его в std::string:
#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находится в <sstream>шапке.
На вопрос был дан ответ. Но я хотел бы добавить конкретный пример.
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;
}
Этот пример требует понимания перегрузки оператора.