Output streams handle output formatting as well as output. Thus, using the toString()
method, clients will not be able to control the formatting of the object as 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 cultural conventions std::cout.imbue(std::locale("")); std::cout << 10000000 << '\n'; // depending on your system configuration may print "10,000,000"
You may not want to allow formatting, so it may not matter.
Another consideration is that output to the stream does not require the entire string representation to be in memory at the same time, but your toString()
method does.
Others have pointed this out, but I think a clearer way of saying that the interface of your classes is not limited only to the methods that it provides, but also includes other functions that you build around it, including non-member functions like both as operator<<
overloads that you provide. Even if this is not a method of your class, you should still think of it as part of your class interface.
Here's an article that talks about this that you might find useful: How non-member functions improve encapsulation
Here is a simple example of operator<<
overloading 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 < mn; ++i) { os << i << ' '; } return os; } int main() { MyClass c = {1000000}; std::cout << c << '\n'; }
source share