【问题标题】:calling a pure virtual function from operator<<从 operator<< 调用纯虚函数
【发布时间】:2015-01-10 02:41:52
【问题描述】:

我不确切知道为什么下面的代码可以编译和工作(它工作得很好)。

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

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

Live on Coliru

你能解释一下为什么我可以在friend std::ostream&amp; operator&lt;&lt;(...) 的实现中调用Base 类中的纯虚函数吗?我认为这应该是不可能的。

【问题讨论】:

  • 为什么不可能?
  • 如果您不能通过指针或对基类的引用来调用纯虚函数,它们就不会很有用。
  • 也许我遗漏了一些东西,但我虽然不能“调用”纯虚函数,只能重载它并在派生类中调用它。
  • 当然可以调用,只是不能实例化一个纯虚函数的类。
  • @CaptainObvlious 我想我问了一个愚蠢的问题 :-/ 当然,你通过参考来称呼它....我周末休息一下 :)

标签: c++ polymorphism


【解决方案1】:

您可以调用纯虚函数,因为当您调用它时,该函数不再是纯虚函数:派生类必须重写它才能停止“抽象”。

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

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

【讨论】:

  • 是的,我弄糊涂了,我是通过引用来称呼它的,所以通常的虚拟调度规则适用......我很惭愧问这个问题......
猜你喜欢
  • 2012-01-28
  • 2011-08-06
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 2012-03-20
相关资源
最近更新 更多