Intermediate openFrameworks - toString

In many languages, there is a function called toString() (or something similar) that exists in most objects that will return a string representation of the object. In these languages, when you write your own classes, you simply override some magic function (like toString()) to add this functionality. This is especially handy for debugging, but can also be used for serialization.

Unfortunately, c++ has no such built-in functionality, but there are a couple of ways to recreate it using some intermediate-level c++ techniques.

Define ostream::operator<< for your class

Printing out a representation of an object is typically used for debugging, and one common way to debug is to use cout (or a stringstream; more about this below). So if you have a class called Rectangle and an instance r, it would be great for debugging to be able to do something like:

cout << "r = " << r << endl;

and it would print a representation of your object to stdout. If you peek at the documentation for cout, you’ll see that cout is an instance of an ostream. By default, ostreams are equipped to handle bool, short, int, char*, and a bunch of other formats using the << operator. So, the goal here is to add Rectangle to that list; to define how ostream behaves when confronted with the << operator and a Rectangle.

TANGENT This general method is called operator overloading, and is super handy for a bunch of purposes. It essentially treats operators as functions that you can override like any other function from a parent class.

Output:

Rectangle(x=10, y=20, width=30, height=40)

On line 19 we take care of defining how an ostream should deal with << Rectangle, and you can see it in use on line 27. The syntax looks a little strange and cryptic IMO, but it makes sense if you read closely. You’ll also notice that on line 14, we declare the ostream& operator<< function to be a friend function of Rectangle. This is optional and simply states that the function can access protected and private member variables of Rectangle.

credit: C++ equivalent of java.toString?

Overload typecast operator

I don’t think I’ve actually ever seen this method in someone else’s code (and there might be a reason for that), but it is the most similar to the method used in Java: defining how to turn the object into a string. Also, it isn’t quite as complicated as the method above.

We start be realizing casting is an “operation” that uses the cast operator: (). And we learned above that operators can be overloaded, so why not overload the (string) operator?

As you can see on line 29, I simply cast r to a string before outputting it using cout. And since cout already knows how to deal with strings, we are golden.

Other string stuff

If you use the ostream::operator<< method, there may be a time when you don’t necessarily want to print the output directly to the console. Perhaps you instead want to draw the string on the screen so that you can see it next to the object. You can accomplish this using another child of ostream, the stringstream and it’s str() method. Take a look:

#include <sstream> // already included by openFrameworks

Rectangle r;
r.init(10, 20, 30, 40);

stringstream ss;
ss  << "r = " << r << endl;
ofDrawBitmapString( ss.str(), 10, 20 );