如果虚函数没有实现,大多数派生类都无法编译,但如果一个基类没有实现虚函数,则可以编译

Dav*_*Lim 2 c++ overriding virtual-functions multiple-inheritance virtual-inheritance

我有一个包含4个类的C++程序:Person,Student,Employee和PartTimeStudent.

Student和Employee都派生自Person,而PartTimeStudent派生自所有3个类(使其成为派生程度最高的类).Person,Student和Employee也有一个名为VDescribe()的派生函数.

请参阅以下代码:

class Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Student : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Employee : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class PartTimeStudent : virtual public Person,
    virtual public Student,
    virtual public Employee
{
    ...
};
Run Code Online (Sandbox Code Playgroud)

注意:在上面的代码片段中,我省略了构造函数,析构函数和成员变量,因为它们与手头的问题无关.

当我尝试编译代码时,我收到以下错误:

override of virtual function "Person::VDescribe" is ambiguous

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescrive(void)'

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescribe(void)'
Run Code Online (Sandbox Code Playgroud)

但是,仅当Student和Employee都实现VDescribe()时才会出现这种情况.如果其中一个类未实现VDescribe(),则编译成功.我仍然会收到警告,例如,如果我从Employee中省略VDescribe(),则会出现以下警告:

'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance
Run Code Online (Sandbox Code Playgroud)

请问为什么会这样?我想知道为什么PartTimeStudent无法编译,如果所有3个类都实现VDescribe(),但如果Student或Employee没有该函数,PartTimeStudent仍然是可编译的.

Rei*_*ica 5

两个覆盖

试想scanario地方StudentEmployee实施VDescribe,而PartTimeStudent没有实现它.您希望此代码如何表现:

PartTimeStudent pts;
pts.VDescribe();
Run Code Online (Sandbox Code Playgroud)

VDescribe应该调用哪个实现?这是模糊的,这正是编译错误的原因.

一个覆盖

什么Employee时候不覆盖VDescribe,情况有点不同.PartTimeStudent然后有以下函数继承:

  • Person::VDescribe被覆盖Student::VDescribe,来自Student
  • Person::VDescribe没有被覆盖,来过Employee.
  • Person::VDescribe没有被覆盖,来过Person.

在这种情况下,Student::VDescribe覆盖Person::VDescribe并且是明确的覆盖,因此编译器能够使用它.但是,它警告您有一个替代的继承路径没有通过此覆盖.此警告在实践中不是很有用,并且是我经常禁用的少数警告之一.


如果你希望你的代码也编译的情况下都StudentEmployee覆盖VDescribe,你确实有覆盖它的PartTimeStudent了.然后该函数将具有明确的最终覆盖,并且代码将编译得很好.您可以使用限定名称调用一个或两个继承的实现.例:

void PartTimeStudent::VDescribe()
{
  Student::VDescribe();
  if (isWorking()) Employe::VDescribe();
}
Run Code Online (Sandbox Code Playgroud)