Я хотел бы контролировать то, что записывается в поток, т. Е. 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;
}
Этот пример требует понимания перегрузки оператора.