Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke an overloaded parent cout friend class from a derived class?

Imagine a setup as follows. How do I invoke the base class cout from within the derived class cout? I could use the getBrand() method, but I feel like I should be able to directly access the base class' cout friend function.

I hacked a bit, and tried this.Brand and also just Brand. No luck.

class Brand {
public:
    Brand(std::string brand):brand_(brand) {};
    friend std::ostream & operator << (std::ostream & out, const Brand & b) {
        out << b.brand_ << ' ';
        return out;
    }   
    std::string getBrand()const { return brand_; }     
private:
    std::string brand_;
}

class Cheese : public Brand {
public:
    Cheese(std::string brand, std::string type):Brand(brand), type_(type) {};
    friend std::ostream & operator << (std::ostream & out, const Cheese & c) {
        out << /* THIS.BRAND?! BRAND?! getBrand() meh.. */ << ' ' << c.type_ << std::endl; // <-- HERE
        return out;
    }
private:
    std::string type_;
}

int main() {
    Cheese c("Cabot Clothbound", "Cheddar");
    std::cout << c << std::endl;
} 

DESIRED OUTPUT

Cabot Clothbound Cheddar
like image 933
kmiklas Avatar asked Jun 19 '17 22:06

kmiklas


4 Answers

You could invoke the overloaded operator << of the Base class from the derived class. Since, you declared the operator as a friend, you could simply cast the the derived class to a base class:

class Cheese : public Brand {
public:
    Cheese(std::string brand, std::string type):Brand(brand), type_(type) {};
    friend std::ostream & operator << (std::ostream & out, const Cheese & c) {

        //ADDED
        out << static_cast<const Brand&>(c) << c.type_ << std::endl;
        return out;
    }
private:
    std::string type_;
};

Output:

Cabot Clothbound Cheddar

See it Live

like image 59
WhiZTiM Avatar answered Sep 21 '22 12:09

WhiZTiM


Cast it, like this:

friend std::ostream& operator<<(std::ostream& out, const Cheese& c)
{
    out << static_cast<const Brand &>(c);
    out << c.type_ << std::endl;

    return out;
}
like image 45
gsamaras Avatar answered Sep 21 '22 12:09

gsamaras


All other answers are responding correctly to your specific question, but whenever you'll try to use polymorphism like this:

Brand const &c = Cheese("Cabot Clothbound", "Cheddar");
std::cout << c << std::endl;

operator << corresponding to Brand will be called instead of Cheese's.

The good way to do it is to use a virtual print member function:

class Brand {
public:
    Brand(std::string const & brand):brand_(brand) {}
    virtual ~Brand() {}
    virtual void print(std::ostream & out) const {
        out << brand_;   
    }
    std::string const & getBrand()const { return brand_; }     
private:
    std::string brand_;
};
class Cheese : public Brand {
public:
    Cheese(std::string const & brand, std::string const & type):Brand(brand), type_(type) {}
    void print(std::ostream & out) const override {
        Brand::print(out); // calling base print()
        out << ' ' << type_ << std::endl;
    }
private:
    std::string type_;
};

Then, you only need a single operator << for the base class which will call your print virtual member function:

std::ostream & operator << (std::ostream & out, const Brand & b) {
    b.print(out);
    return out;
}

DEMO

like image 27
O'Neil Avatar answered Sep 18 '22 12:09

O'Neil


You obviously can't do anything like Brand::operator<<, because both operator<< are defined as friend and thus they are not member functions.

If you want to invoke operator<<(std::ostream&, const Brand&), you just have to pass correct types to that, and since Derived classes can be easily casted to Base classes, you can just do

friend std::ostream & operator << (std::ostream & out, const Cheese & c) {
    out << static_cast<const Brand&>(c) << ' ' << c.type_ << std::endl;
    return out;
}
like image 28
Zereges Avatar answered Sep 19 '22 12:09

Zereges