'Printing a message from a base class function through the operator <<

This is the header file with class Rectangle that inherits from class Shape:

class Rectangle: public Shape {

  private:
    double width;
    double height;

  protected:

    // overrides the base class's toString implementation.
    // returns a string representation of the class. The method returns the value of id, name, width, height separated by an @:
    // <<value of id>>@<<value of name>>@<<value of width>>@<<value of height>>
    // note that you must reuse the base class's toString implementation. Don't repeat code from the base class
    string toString() const;

Now this is a an operator<< from class Rectangle:

// Overloads the standard output stream operator to print the message from toString() to the standard output stream
friend ostream& operator<<(ostream &os, const Rectangle *rectangle);

This is my code for the Rectangle.cpp:

ostream& operator<<(ostream& os, Rectangle* rectangle) {
    os << *rectangle.toString();
    return os;
}

It's telling me that the expression must have a class type. Please help.

BTW, this is the toString() function that I declared in the Rectangle.cpp:

string Rectangle::toString() const {
    return to_string(this->id) + "@" + this->name + "@" + to_string(this->width) + to_string(this->height);
}


Solution 1:[1]

The problem is that you've made the second parameter of the overloaded operator<< to be a pointer(const Rectangle *) whereas it should be a reference(const Rectangle &) as shown below. Note that this is a problem because due to operator precedence the expression *rectangle.toString() is equivalent to:

*(rectangle.toString())  //equivalent to this because of operator precedence

But the above can't work as rectangle is a pointer type.

Additionally, you were missing a low-level const in the second parameter of the overloaded operator<< while defining it. This is also fixed in the below shown demo.


Solution

There are two ways to solve this. You can either make the second parameter a const Rectangle& or change the expression *rectangle.toString() to rectangle->toString().

Method 1

class Rectangle{
//------------------------------------------------------v------------>note the lvalue reference
friend ostream& operator<<(ostream &os, const Rectangle &rectangle);

//other code here
}
//------------------------------vvvvv-----------v--------------->const and & added here
ostream& operator<<(ostream& os,const  Rectangle& rectangle) {
    os << rectangle.toString();
//-------^------------------------>removed the * from here
    return os;

}

Demo


Method 2

//------------------------------vvvvv-------------------------->const added here
ostream& operator<<(ostream& os,const Rectangle* rectangle) {
    os << rectangle->toString();
//-----------------^^--------------->  here we have used ->
    return os;
}

Demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1