是否需要在派生类中实现所有虚函数?

mik*_*aub 84 c++ inheritance

这似乎是一个简单的问题,但我无法在其他任何地方找到答案.

假设我有以下内容:

class Abstract {
public:
    virtual void foo() = 0;
    virtual void bar();
}

class Derived : Abstract {
public:
    virtual void foo();
}
Run Code Online (Sandbox Code Playgroud)

类Derived是否可以实现bar()函数?如果不是我的所有派生类都需要bar()函数,但有些人会这样做.是否需要在派生类中实现抽象基类的所有虚函数,还是只需要纯虚拟的?谢谢

Rob*_*edy 74

派生类也没有必须实现所有的虚函数本身.他们只需要实现纯粹的.1这意味着问题中的Derived类是正确的.它从其祖先类继承bar实现Abstract.(这假设在Abstract::bar某处实现.问题中的代码声明了方法,但没有定义它.您可以将其定义为内联,如Trenki的答案所示,或者您可以单独定义它.)


1即便如此,只有派生类才会被实例化.如果派生类没有直接实例化,而只是作为更多派生类的基类存在,那么它就是那些负责实现所有纯虚方法的类.允许层次结构中的"中间"类保留一些未实现的纯虚方法,就像基类一样.如果"中间"类确实实现了纯虚方法,那么它的后代将继承该实现,因此它们不必自己重新实现它.

  • 甚至这个(纯虚函数的实现)只有在它们被打算实例化的时候(与自己的抽象基类相反). (2认同)
  • @Rob:"他们只需要实现纯粹的."它具有误导性.派生类不一定*需要*来实现*pure*虚函数. (2认同)

tre*_*nki 44

只有纯虚方法必须在派生类中实现,但您仍需要其他虚方法的定义(而不仅仅是声明).如果您不提供,链接器可能会抱怨.

因此,只需{}在可选的虚拟方法之后添加一个空的默认实现:

class Abstract {
public:
    virtual void foo() = 0; // pure virtual must be overridden
    virtual void bar() {}   // virtual with empty default implementation
};

class Derived : Abstract {
public:
    virtual void foo();
};
Run Code Online (Sandbox Code Playgroud)

然而,更复杂的默认实现将进入单独的源文件.


Alo*_*ave 7

ISO C++标准指定必须定义非纯虚拟类的所有虚方法.

简单地说规则是:
如果你的派生类超过了基类的虚方法,那么它也应该提供一个定义,如果没有,那么Base类应该提供该方法的定义.

根据代码示例中的上述规则,virtual void bar();需要Base类中的定义.

参考:

C++ 03标准:10.3虚函数[class.virtual]

在类中声明的虚函数应在该类中定义或声明为纯(10.4),或两者兼有; 但不需要诊断(3.2).

因此,您应该将函数设置为纯虚拟或为其提供定义.

gcc的常见问题 doccuments它还有:

ISO C++标准指定必须定义非纯虚拟类的所有虚方法,但不要求违反此规则的任何诊断[class.virtual]/8.基于此假设,GCC将仅在翻译单元中发出隐式定义的构造函数,赋值运算符,析构函数和类的虚拟表,以定义其第一个此类非内联方法.

因此,如果您未能定义此特定方法,链接器可能会抱怨缺少明显不相关的符号的定义.不幸的是,为了改进此错误消息,可能需要更改链接器,并且不能总是这样做.

解决方案是确保定义所有非纯的虚方法.请注意,即使声明为pure-virtual,也必须定义析构函数[class.dtor]/7.