user13040283
user13040283

Reputation:

Inheritance - Operator overloading

I have two classes, base and derived. In main I have a vector which is *base type and contains one base object and one derived object. I have overloaded output operator for both classes, but when I print the vector for derived class, base output operator is called although I have overloaded it separately. What should I change in my program to change output from:

12
30

to

12
30 31

?

This is the code:

#include <iostream>
#include <vector>

using namespace std;
class base {
    int x;
public:
    base(int _x) : x(_x) {}
    friend ostream& operator<<(ostream& out, base obj) {
            return out << obj.x;
    }
};

class derived : public base {
    int y;
public:
    derived(int _x, int _y) : base(_x), y(_y) {}
    friend ostream& operator<<(ostream& out, derived obj) {
            return out << (base) obj << ' ' << obj.y;
    }
};

int main() {
        vector<base*> vec;
        base* a = new base(12);
        derived* b = new derived(30,31);
        vec.push_back(a);
        vec.push_back(b);
        for (auto p: vec) cout << *p << '\n';
}

Upvotes: 2

Views: 84

Answers (1)

R Sahu
R Sahu

Reputation: 206567

Dynamic dispatch, based on the underlying object, works only for virtual member functions. It does not work for non-member functions or non-virtual member functions.

One way to get around the problem would be:

  1. Use the friend function using the base type.
  2. Change the argument type for obj to be a const reference.
  3. From that function, call a virtual member function to do the real work.
class base {
    int x;
public:
    base(int _x) : x(_x) {}

    virtual std::ostream& write(std::ostream& out) const
    {
       return (out << x);
    }

    // Change obj to be a const reference
    friend std::ostream& operator<<(std::ostream& out, base const& obj)
    {
        return obj.write(out);
    }
};

class derived : public base {
    int y;
public:
    derived(int _x, int _y) : base(_x), y(_y) {}

    virtual std::ostream& write(std::ostream& out) const
    {
       // Let the base class take care of its part.
       base::write(out);

       // Now take care of this class part.
       return ( out << ' ' << y);
    }

    // This is useless now.
    // friend ostream& operator<<(ostream& out, derived obj) {
    //         return out << (base) obj << ' ' << obj.y;
    // }
};

PS Why is "using namespace std;" considered bad practice?

Upvotes: 2

Related Questions