Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
653 views
in Technique[技术] by (71.8m points)

c++ - virtual insertion operator overloading for base and derived class

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;
    }
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...