It's easy enough in Java. How is it done in C++?


for e.g. I have a class called Relation, that has a name field (just a string) and then a vector of strings.
I want to specify that wherever I type (for example):

Relation* r = new Relation(...);
cout << *r << endl;

...the relation should get printed as:

<relation-name>(each string stored in the vector, separated by commas)

Please help. :eek:

Recommended Answers

All 4 Replies

For any user-defined type, you can overload operator<< for output to ostreams:

ostream& operator<<(ostream& out, const Relation& r)
{
  return out<< r.toString();
}

Then all you need to do is define Relation::toString to return a string in the format that you want.

Pretty simple really, and overloading operators can be a powerful and flexible tool.

Thanks.

And... I need to stick that snippet of code into the Relation.h file?

apcxpc,

I accomplished this a different way which is to define a class Printable, which defines a toString function that returns a const string. You can then descend your classes from Printable. Any other class that wants to print one of your objects can just deal with a Printable object instead of your class directly, as long as you define a toString method.

class Printable
{
 
 public:
 virtual  const string toString() =0;
};
#endif
 
example of use:
class StringPair : public Printable
{
  ...etc...
const string toString()
 {
  return "TAG:[" + value +  "] VALUE:[" + value +"]";
 }
};
 
in class that accepts a printable
 void FileLog::writeLog( Printable &a )
{
 writeLog(a.toString());
}

>And... I need to stick that snippet of code into the Relation.h file?
This is a tricky question because if I tell you one right way to do it, you'll probably get it wrong (most people have a problem with how to organize multiple files). If I tell you another right way to do it, you'll probably shrug it off as too complicated because it involves templates. So yes, put it in the Relation.h file, but be aware that it's not a good solution.

If you want to do it right then place the code I gave you in the Relation.cpp file that should be the companion to Relation.h (where the .h file holds declarations and the .cpp file holds definitions). In Relation.h, you put a declaration:

ostream& operator<<(ostream& out, const Relation& r);

Another way to do it, which happens to also be a more flexible solution anyway, is to make operator<< a template function, and place it in the Relation.h file (for obscure reasons that I won't get into):

template <typename CharT, typename Traits>
basic_ostream<CharT, Traits>& operator<<(
  basic_ostream<CharT, Traits>& out, const Relation& r)
{
  return out<< r.toString();
}

basic_ostream is the template class hidden behind the ostream typedef. Now you can use the operator with other character encodings and type traits (such as Unicode) without changing anything.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.