2

I'm coming back to c++ after using Java for a long time. In Java overriding the toString method on an object allows the object to be automatically translated into a string and concatenated to other strings.

class Test {
    public static void main(String[] args) {
        System.out.println(new Test() + " There"); // prints hello there
    }

    public String toString() {
        return "Hello";
    }
}

Is there anything similar that would allow me to stream an object into cout?

cout << Test() << endl;

2 Answers 2

5

The equivalent is to overload operator<<:

#include <ostream>

class Test
{
  int t;
};

std::ostream& operator<<(std::ostream& os, const Test& t)
{
   os << "Hello";
   return os;
}

You would then use it like this:

#include <iostream>

int main()
{
  std::cout << Test() << " There" << std::endl;
}

See the code in action: http://codepad.org/pH1CVYPR

Sign up to request clarification or add additional context in comments.

10 Comments

Overload, not override (override implies that an operator<< for ostream and Test already exists and you are overriding it).
You may want to consider defining the operators for streams taking other kind of characters/traits as well.
@Matteo: Thanks, I used the wrong one in haste and have fixed it.
template< typename Char, typename Traits > std::basic_ostream< Char, Traits >& operator<<(std::basic_ostream< Char, Traits >& os, const Test& t) will work for all kind of output streams, including std::wcout for instance which is the equivalent of std::cout specified for wchar_t types.
@Bill: Besides the fact that your declaration of the operator is a no-op, the obvious difference between your version and mine is that mine only works for basic_ostream types while yours would work for anything, giving a compile time error if the os << t operation is not well formed for that particular os, or worse silently doing who knows what if the expression is valid and os is not an output stream. Also, note that the full implementation for the output insertion is a bit more complex than just `os << "Hello", as pointed out by @Matteo Italia.
|
2

The common idiom is to create an overload of operator<< that takes an output stream as the left-hand operand.

#include <iostream>

struct Point
{
    double x;
    double y;
    Point(double X, double Y)
      : x(X), y(Y)
    {}
};

std::ostream & operator<<(std::ostream & Stream, const Point & Obj)
{
    // Here you can do whatever you want with your stream (Stream)
    // and the object being written into it (Obj)
    // For our point we can just print its coordinates
    Stream<<"{"<<Obj.x<<", "<<Obj.y<<"}";
    return Stream; // return the stream to allow chained writes
}

int main()
{
    Point APoint(10.4, 5.6);
    std::cout<<APoint<<std::endl; // this will print {10.4, 5.6}
    return 0;
}

If you want to support streams with other character types (e.g. wchar_t)/template parameters of the streams you have to write different overloads for the various types of streams you want to support, or, if your code is (more or less) independent from such types, you can simply write a template operator<<.

1 Comment

@Kerrek: sure, that's what I meant with the "template operator<<".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.