简体   繁体   中英

Polymorphism does not work with pointers, operator<< overload, inheritance, C++

I have a problem with my code. I have two classes, A and B , and B inherits A . I also have operators << overloaded in both classes.

Everything works, I have no compiler errors, but it seems something is wrong. As far as I understand polymorphism, when I use pointers to base class while creating child class with new , calling a method should match the child class, not the base class.

For the code below,

#include <iostream>
using namespace std;

class A
{
    protected:
        int a;

    public:

    A(int aa) : a(aa) {};

    virtual void show(ostream& o) const
    {
        o << "a  = " << a << "\n";
    }
};

ostream& operator << (ostream& os, const A &o)
{
    o.show(os);
    return os;
}

class B : public A
{
    private:
        int b;
    public:
        B(int bb, int aa) : A(aa), b(bb){}
        int getb() const {return b;}
};

ostream & operator << ( ostream & os, const B & o)
{
    os << static_cast <const A &>(o);
    os << "\n";
    os << "b = " << o.getb() << "\n";
    return os;
}

int main()
{
    A *o1 = new B(2,3);
    cout << *o1;

    cout << "---------------------\n";

    B *o2 = new B(2,3);
    cout << *o2;

    return 0;
}

In main:

A *o1 = new B(2,3);
cout << *o1;

Shows a = 3 , instead of showing a = 3 b = 2 (the call should match the child class, not the base class). The thing is, I need to implement the << and >> operators in every child class, but I think they do not behave as they should.

The output of the program:

在此处输入图片说明

Even the modified code with re-implmented show method shows wrong results, it does not show a at all this time:

#include <iostream>
using namespace std;

class A
{
protected:
    int a;

public:

    A(int aa) : a(aa) {};

    virtual void show(ostream& o) const
    {
        o << "a  = " << a << "\n";
    }
};

ostream& operator << (ostream& os, const A &o)
{
    o.show(os);
    return os;
}

class B : public A
{
private:
    int b;
public:
    B(int bb, int aa) : A(aa), b(bb) {}
    int getb() const
    {
        return b;
    }

    void show(ostream& o) const
    {
        o << "b  = " << b << "\n";
    }
};

ostream & operator << ( ostream & os, const B & o)
{
    os << static_cast <const A &>(o);
    o.show(os);
    return os;
}

int main()
{
    A *o1 = new B(2,3);
    cout << *o1;

    cout << "---------------------\n";

    B *o2 = new B(2,3);
    cout << *o2;

    return 0;
}

enter image description here

you have to implement the virtual function show in derived class B:

class B: public A
{
     public:
         // some code here
         virtual void show(ostream& o) const
        {
            o << "b  = " << b << "\n";
        } 
};

when I use pointers to base class while creating child class with new, calling a method should match the child class, not the base class

It does when you call a member function ("method" in some other languages), but operator<< is not a member function – it's an overloaded free function.
When choosing an overload, only the types known at compile-time are used.

Since o1 is an A* , *o1 is an A& , and the overload for A& is chosen.

You're doing this a bit "backwards"; you only need one operator<< , for the base class, which calls the virtual show , and then you override show in the derived classes.

Like this:

class A
{
    // ...
    virtual void show(ostream& o) const
    {
        o << "a  = " << a << "\n";
    }
};

ostream& operator << (ostream& os, const A &o)
{
    o.show(os);
    return os;
}

class B : public A
{
    // ...
    void show(ostream& o) const override
    {
        A::show(o); // Do the "A part".
        o << "b  = " << b << "\n";
    }
};

Follow the same pattern for operator>> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM