Overloading << operator for std::ostream

2019-02-18 23:34发布

问题:

ostream& operator <<(ostream& osObject, const storageRentals& rentals)
{
    osObject << rentals.summaryReport();
    return osObject;
}

summaryReport() is a void function, and it is giving me an error:

no operator "<<" matches these operands

but the error is not there if I change the summaryReport function to an int, but the problem I have with that is you have to return a value, and it is printing it out on the screen.

void storageRentals::summaryReport() const
{
   for (int count = 0; count < 8; count++)
      cout << "Unit: " << count + 1 << "    " << stoUnits[count] << endl;
}

Is there any way to overload cout << with a void function?

回答1:

You should define summartReport taking ostream& as parameter, as shown here:

std::ostream&  storageRentals::summaryReport(std::ostream & out) const
{
    //use out instead of cout
    for (int count = 0; count < 8; count++)
        out << "Unit: " << count + 1 << "    " << stoUnits[count] << endl;

    return out; //return so that op<< can be just one line!
}

then call it as:

ostream& operator <<(ostream& osObject, const storageRentals& rentals)
{
    return rentals.summaryReport(osObject); //just one line!
}

By the way, it is not called "overloading cout". You should say, "overloading operator<< for std::ostream.



回答2:

If you overload cout, you may make some other place using code hard to understand, or more confusing. In fact, you could make your own class to complete the work. e.g. make a class class MyPring, and overload its operator <<.



回答3:

Your storage report implicitely is always streamed to cout. Imagine someone calling your function this way and having the rentals on cout instead of the file.

fstream fs("out.txt");
storageRentals rentals;
fs << rentals;

Why don't you stream your class like this:

ostream& operator <<(ostream& osObject, const storageRentals& rentals)
{

  for (int count = 0; count < 8; count++) {
      osObject << "Unit: " << count + 1 << "    " << rentals.stoUnits[count] << endl;
  }
  return osObject;
}

If the stoUnits member is private you need to make the stream function a friend of your storage class.

friend ostream& operator<<(ostream& osObject, const storageRentals& rentals);


回答4:

There are two things you need to do here. Make storageRentals::summaryReport() take an std::ostream& (you can default this to std::cout):

void storageRentals::summaryReport(std::ostream& os) const
{
    for (int count = 0; count < 8; count++)
    {
        os << "Unit: " << count + 1 << "    " << stoUnits[count] << endl;
    }
}

Then call it thus:

ostream& operator <<(ostream& osObject, const storageRentals& rentals)
{
    rentals.summaryReport(osObject);
    return osObject;
}

Note: An advantage of making storageRentals::summaryReport() take an std::ostream& is that you can pass it an std::ostringstream in your unit-tests and assert that it is providing correct output.