我有一个带有4个类的C++程序:人员,学生,员工和PartTimeStudent。

Student和Employee分别从Person派生,而PartTimeStudent从所有3个类派生(使其成为派生最多的类)。人员,学生和雇员还具有称为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
{
    ...
};

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

当我尝试编译代码时,出现以下错误:
override of virtual function "Person::VDescribe" is ambiguous

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

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

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

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

最佳答案

两个替代

想象一下scanario,其中StudentEmployee实现VDescribe,而PartTimeStudent不实现它。您如何看待此代码的行为:

PartTimeStudent pts;
pts.VDescribe();

应该调用哪种VDescribe实现?这是模棱两可的,这正是编译出错的原因。

一个替代

Employee不覆盖VDescribe时,情况有所不同。 PartTimeStudent然后具有以下要继承的功能:
  • Person::VDescribeStudent::VDescribe覆盖,通过Student
  • Person::VDescribe未覆盖,通过Employee传入。
  • Person::VDescribe未覆盖,通过Person传入。

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

    如果您还希望在StudentEmployee都覆盖VDescribe的情况下也编译代码,则实际上您也必须在PartTimeStudent中覆盖它。然后,该函数将具有明确的最终替代程序,并且代码将正常编译。您可以使用限定名称来调用一个或两个继承的实现。例:
    void PartTimeStudent::VDescribe()
    {
      Student::VDescribe();
      if (isWorking()) Employe::VDescribe();
    }
    

    10-07 13:06