Output streams handle output formatting as well as output. So with your toString()
method clients won't be able to manage the formatting for the object the way they do for everything else:
// set specific formatting options for printing a value
std::cout << std::scientific << std::setprecision(10) << 10.0 << '\n'; // prints 1.0000000000e+01
// set formatting based on user's cultural conventions
std::cout.imbue(std::locale(""));
std::cout << 10000000 << '\n'; // depending on your system configuration may print "10,000,000"
Perhaps you don't care to allow any formatting so perhaps this won't matter.
Another consideration is that outputting to a stream doesn't require that the entire string representation be in memory at once, but your toString()
method does.
Others have pointed this out, but I think a clearer way of saying it is that your classes interface is not limited to just the methods it provides, but also includes the other functions you build around it, including non-member functions such as the operator<<
overloads you provide. Even though it's not a method of your class you should still think of it as part of your class's interface.
Here's an article that talks about this which perhaps you will find helpful: How Non-Member Functions Improve Encapsulation
Here's a simple example of overloading operator<<
for a user defined class:
#include <iostream>
struct MyClass {
int n;
};
std::ostream &operator<< (std::ostream &os, MyClass const &m) {
for (int i = 0; i < m.n; ++i) {
os << i << ' ';
}
return os;
}
int main() {
MyClass c = {1000000};
std::cout << c << '\n';
}
int
? Or do you meanto_string
? – Sheatheostream& operator<<
. If you want to make strings out of it, give it a to_string member. – Hypaethral