171

I'd like to control what is written to a stream, i.e. cout, for an object of a custom class. Is that possible in C++? In Java you could override the toString() method for similar purpose.

Zoe stands with Ukraine
  • 25,310
  • 18
  • 114
  • 149
Bogdan Balan
  • 6,151
  • 8
  • 24
  • 23

5 Answers5

194

In C++ you can overload operator<< for ostream and your custom class:

class A {
public:
  int i;
};

std::ostream& operator<<(std::ostream &strm, const A &a) {
  return strm << "A(" << a.i << ")";
}

This way you can output instances of your class on streams:

A x = ...;
std::cout << x << std::endl;

In case your operator<< wants to print out internals of class A and really needs access to its private and protected members you could also declare it as a friend function:

class A {
private:
  friend std::ostream& operator<<(std::ostream&, const A&);
  int j;
};

std::ostream& operator<<(std::ostream &strm, const A &a) {
  return strm << "A(" << a.j << ")";
}
sth
  • 211,504
  • 50
  • 270
  • 362
  • 5
    Better yet declare it as `friend`, and also inside the body of the class - with that, you won't have to do `using namespace` for the namespace containing the operator (and the class), but ADL will find it so long as object of that class is one of operands. – Pavel Minaev Oct 11 '09 at 05:45
  • ... the above was meant to say "_define_ it as friend inside the body of the class" - as in, an inline member definition. – Pavel Minaev Oct 11 '09 at 05:48
  • 2
    @fnieto: that `dump` public method is dirty and unnecessary. Using `friend` here is perfectly fine. Whether you prefer a redundant method or an intrusive `friend` is entirely a matter of taste, although `friend` has arguably been introduced for this exact purpose. – Konrad Rudolph Oct 11 '09 at 13:32
  • 1
    @Pavel: Argument dependent lookup will find it anyway, as long as the operator is defined in the same namespace as the class. This has nothing to to with friends and doesn't need it to be declared/defined inside the class. Also, making `operator< – sth Oct 11 '09 at 13:37
55

You can also do it this way, allowing polymorphism:

class Base {
public:
   virtual std::ostream& dump(std::ostream& o) const {
      return o << "Base: " << b << "; ";
   }
private:
  int b;
};

class Derived : public Base {
public:
   virtual std::ostream& dump(std::ostream& o) const {
      return o << "Derived: " << d << "; ";
   }
private:
   int d;
}

std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
Fernando N.
  • 6,239
  • 4
  • 25
  • 30
32

In C++11, to_string is finally added to the standard.

http://en.cppreference.com/w/cpp/string/basic_string/to_string

Zhaojun Zhang
  • 479
  • 4
  • 10
  • 17
    This is a useful addition to this page, however the C++ implementation is significantly different to the one in Java/C#. In those languages, `ToString()` is a virtual function defined on the base class of *all* objects, and is therefore used as a standard way to express a string representation of any object. These functions on `std::string` only apply to built-in types. The idiomatic way in C++ is to override the `< – Drew Noakes Mar 01 '13 at 20:26
  • 11
    The "ugliness" of the standard signature of `operator< – P Marecki Jan 19 '16 at 22:27
12

As an extension to what John said, if you want to extract the string representation and store it in a std::string do this:

#include <sstream>    
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace

std::stringstream is located in the <sstream> header.

einpoklum
  • 102,731
  • 48
  • 279
  • 553
blwy10
  • 4,844
  • 2
  • 23
  • 23
10

The question has been answered. But I wanted to add a concrete example.

class Point{

public:
      Point(int theX, int theY) :x(theX), y(theY)
      {}
      // Print the object
      friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
      int x;
      int y;
};

ostream& operator <<(ostream& outputStream, const Point& p){
       int posX = p.x;
       int posY = p.y;

       outputStream << "x="<<posX<<","<<"y="<<posY;
      return outputStream;
}

This example requires understanding operator overload.