Я хотів би контролювати те, що записується в потік, тобто 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 тонінгрінг нарешті додається до стандарту.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
ToString()
є віртуальна функція, визначена в базовому класі всіх об'єктів, і тому використовується як стандартний спосіб вираження рядкового подання будь-якого об'єкта. Ці функції стосуються std::string
лише вбудованих типів. Ідіоматичний спосіб у C ++ - це перекриття <<
оператора для користувацьких типів.
operator<<
порівняно з простою String
семантикою Java спонукає мене зауважити, що to_string()
це не лише "корисне доповнення", але новий бажаний спосіб зробити це на C ++. Якщо, як це стосується ОП, 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;
}
Цей приклад вимагає розуміння перевантаження оператора.