I'd like to control what is written to a stream, i.e. cout, for an object of a custom class. Is that possible in C++? In Java you could overwride the toString() method for similar purpose. Thanks
+19
A:
In C++ you can overload operator<<
for ostream
and your custom class:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
This way you can output instances of your class on streams:
A x = ...;
std::cout << x << std::endl;
In case your operator<<
wants to print out internals of class A
and really needs access to it's private and protected members you could also declare it as a friend function:
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 << ")";
}
sth
2009-10-11 05:33:49
It is better to declare the operator<< as friend function of the class as it might be required to access the private members of the class.
Naveen
2009-10-11 05:36:07
Better yet declare it as `friend`, and also inside the body of the class - with that, you won't have to do `using namespace` for the namespace containing the operator (and the class), but ADL will find it so long as object of that class is one of operands.
Pavel Minaev
2009-10-11 05:45:23
... the above was meant to say "_define_ it as friend inside the body of the class" - as in, an inline member definition.
Pavel Minaev
2009-10-11 05:48:29
@Naveen, that friend is dirty and unnecessary. Write a dump public method, and call it from a free operator<< function.
fnieto
2009-10-11 08:46:14
@fnieto: that `dump` public method is dirty and unnecessary. Using `friend` here is perfectly fine. Whether you prefer a redundant method or an intrusive `friend` is entirely a matter of taste, although `friend` has arguably been introduced for this exact purpose.
Konrad Rudolph
2009-10-11 13:32:53
@Pavel: Argument dependent lookup will find it anyway, as long as the operator is defined in the same namespace as the class. This has nothing to to with friends and doesn't need it to be declared/defined inside the class. Also, making `operator<<()` a member function won't work: you would have to make it a member function of `std::ostream` for it to accept a left hand operand of type `std::ostream`.
sth
2009-10-11 13:37:15
@Konrad: you are already making public dump functionality trough operator<<, so I don't see anything dirty about its public access. dump method has nothing to do with the friend but with polymorphic behavior, you could make dump private and keep the friend but I insist, it is ugly and unnecessary.
fnieto
2009-10-11 14:23:05
sprintf is a C not C++ construct, as such it does not have the notion of the representation of a custom class, plus it does not play nice with iostream.
Chen Levy
2009-10-11 05:39:57
sprintf_nuf_said, given your user name I understand that you have a certain affinity for sprintf. I do think that its suitability in this particular case can be questioned, but I certainly expect many more sprintf-centered answers from you! How do you do this in SQL? sprintf! How do I do that in Java? sprintf! How does a hash table work? sprintf! What is important to think of when managing a large programming project? sprintf!
Thomas Padron-McCarthy
2009-10-11 08:37:42
+2
A:
As an extension to what John said, if you want to extract the string representation and store it in a std::string
do this:
// 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
is located in the <sstream>
header.
blwy10
2009-10-11 06:16:26
+3
A:
You can do it without unnecessary friends and allowing polymorphism, this way:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
fnieto
2009-10-11 08:27:38