通过在派生类中使纯虚函数“隐藏”基类虚函数是否有效?

时间:2019-01-23 15:47:49

标签: c++ c++11 language-lawyer

考虑示例:

#include <iostream>

class A {
    public:
    virtual void f();
};

void A::f()
{
    std::cout << "f() from A\n";
}

class B: public A {
    public:
    virtual void f() = 0;
};

class C: public B {
    public:
    void f();
};

void C::f()
{
    std::cout << "f() from C\n";
}

int main()
{
    C o;
    o.f();
}

A::f()实现是C类的“隐藏”,它为f()提供了自己的实现-有效地使A::f()变得毫无意义。在这样的类层次结构设计中我看不到什么价值,但是我的问题是这是有效的C ++还是仅仅是“有效的”(例如未定义的行为)?

5 个答案:

答案 0 :(得分:22)

该标准明确允许并支持(例如,参见this在线C ++标准草案),因此显然不是不确定的行为:

  

10.4抽象类

     

5 [注意:抽象类可以从非抽象类派生。   抽象,纯虚拟函数可能会覆盖虚拟函数   这不是纯粹的。 —尾注]

结果是您的类B变成了抽象,并且任何子类(如果也不应是抽象的)都必须定义f();仍然可以通过A调用类A::f()中的实现,因此-从重用实现的角度来看-不是没有意义的。

答案 1 :(得分:3)

这将安全地实现要求C的作者为f()提供实现的目标。

我会问为什么需要这样做-如果基本实现在您的设计中不是“有效”,那么它为什么存在,和/或为什么virtual

无论如何,他们仍然可以调用A::f(),因此是否可以将其视为“隐藏”尚有争议。

答案 2 :(得分:2)

  

我的问题是这是有效的C ++还是仅仅是“有效的”(例如未定义的行为)?

程序的行为已明确定义。

  

有效地使A::f()变得毫无意义。

当然,如果您从不调用函数,则确实不需要定义函数。为了明确起见,如果您确实选择忽略定义,则必须将函数声明为纯虚函数(反之则不成立;您可以可以定义纯虚函数)。

答案 3 :(得分:2)

这是有效且定义明确的C ++。

如果您想强制您的类的用户实现已经在基类中实现的方法(并且不想使用其他名称,这将是一个更明显的选择),它有时会很有用。实现操作系统消息泵的GUI库是一个应用程序。

答案 4 :(得分:2)

据我所知,没有未定义的行为= 0仅表示派生类必须覆盖它。但是您仍然可以在同一类中为该函数提供离线定义。