从运算符调用纯虚函数<<

时间:2015-01-10 02:41:52

标签: c++ polymorphism

我不确切知道为什么下面的代码会编译并运行(效果很好)。

#include <iostream>

struct Base
{
    virtual std::ostream& display(std::ostream& os) const = 0;
    friend std::ostream& operator<<(std::ostream& lhs, const Base& rhs)
    {
        return rhs.display(lhs);
    }
};

struct A: Base
{
    virtual std::ostream& display(std::ostream& os) const
    {
        return os << "A" << std::endl;
    }
};

struct B: A
{
    virtual std::ostream& display(std::ostream& os) const
    {
        return os << "B" << std::endl;
    }
};

int main()
{
    A a;
    std::cout << a << std::endl;

    B b;
    std::cout << b << std::endl;
}

我只在operator<<类中定义Base一次,它调用纯virtual display函数。此方案通常用于避免在派生类中重写operator<<,即在基类中只定义一次,然后使用另一个函数的虚拟调度(在我的例子中,display())。

参见 Live on Coliru

你能解释为什么我能够在Base的实现中调用friend std::ostream& operator<<(...)类中的纯虚函数吗?我认为这不可能。

1 个答案:

答案 0 :(得分:3)

你可以调用纯虚函数,因为当你调用它时,函数不再是纯虚函数:派生类必须覆盖它才能停止抽象&#34;抽象&#34;。

编译器知道你不能自己实例化类Base。这意味着您无法在任何不为您的纯虚函数提供合适覆盖的类上调用operator <<。这就是为什么编译器允许你进行调用:它知道在运行时会有一个实现。

注意:调用纯虚函数的唯一方法是从基类的构造函数中调用它。由于该函数是纯虚函数,因此会导致未定义的行为;现代编译器警告你这个问题。