virtual insertion operator overloading for base and derived class

我的未来我决定 提交于 2021-02-05 11:34:07

问题


Can someone please explain how to ensure that the derived function is called from a pointer of type base to a derived object instead of the base function...

Also, are the virtual and override keywords best practice to accomplish this?

I had previously defined each overload with keyword friend in each class; but the base function was called for the base pointer to derived object.

int main()
{  
    // contrived example ...
    base* ptr_derived = new derived();
    std::cout << *ptr_derived;

    delete ptr_derived;
}
class base 
{
    virtual std::ostream& operator<<(std::ostream output)
    {
        output << // base details... 
        return output;
    }
};

class derived : public base
{
    std::ostream& operator<<(std::ostream output) // override?
    {
        output << // derived details...
        return output;
    }
};

回答1:


Virtual functions work by calling the correct function through a pointer in something called the vtable. So, some offset from this gives a pointer to the vtable, and some offset into the vtable gives the address of the function for that actual type of object.

However, this won't work (directly) with an overload of operator<< for inserting an object into a stream. A virtual function must be a member function--but when you're overloading a member function, its left operand must be an object of the type for which you're providing an overload. That is, with an overloaded member function, a << b is invoked as a.operator<<(b);. For stream insertion that won't work, because the left operand is always the stream rather than the type you're going to insert into the stream.

To get around that, you do make the operator itself a friend (which is never a member).

To get virtual behavior, you have that invoke a virtual member function:

class base { 
public:
    virtual std::ostream &write(std::ostream &os) const { 
        // write myself to the passed stream
        return os;
    }

    friend std::ostream &operator<<(std::ostream &os, base const &b) { 
       return b.write(os);
    }
};

class derived : public base {
public:
    std::ostream &write(std::ostream &os) const override { 
        // write myself to the passed stream
        return os;
    }
};

Now the overloaded operator gets called for the correct types. It, in turn, just invokes the correct virtual function for the object that was actually passed (base, derived, or some other derived class if you choose to create one).




回答2:


operator<< has to be non-member function, you can't make them virtual. You have to make another virtual member function, and call it in operator<< to make runtime dispatch work. e.g.

class base 
{
    friend std::ostream& operator<<(std::ostream& output, const base& b)
    {
        b.print(output);
        return output;
    }
    virtual void print(std::ostream& output) const {
        output << // base details... 
    }
public:
    virtual ~base() = default;
};

class derived : public base
{
    virtual void print(std::ostream& output) const override {
        output << // derived details...
    }
};


来源:https://stackoverflow.com/questions/50979946/virtual-insertion-operator-overloading-for-base-and-derived-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!