我有一个包含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
{
...
};
注意:在上面的代码片段中,我省略了构造函数,析构函数和成员变量,因为它们与手头的问题无关。
当我尝试编译代码时,出现以下错误:
override of virtual function "Person::VDescribe" is ambiguous
'PartTimeStudent': ambiguous inheritance of 'void Person::VDescrive(void)'
'PartTimeStudent': ambiguous inheritance of 'void Person::VDescribe(void)'
但是,只有学生和员工都实施VDescribe()时才会出现这种情况。如果其中一个类未实现VDescribe(),则编译成功。我仍然会收到警告,例如如果我从Employee中省略VDescribe(),则会出现以下警告:
'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance
请问为什么会这样?我想知道为什么PartTimeStudent无法编译,如果所有3个类都实现VDescribe(),但如果Student或Employee没有该函数,PartTimeStudent仍然是可编译的。
答案 0 :(得分:5)
想象一下scanario Student
和Employee
实施VDescribe
,而PartTimeStudent
没有实现它。您希望这段代码表现如何:
PartTimeStudent pts;
pts.VDescribe();
应该调用VDescribe
的哪个实现?这是模糊的,这正是编译错误的原因。
当Employee
未覆盖VDescribe
时,情况会有所不同。 PartTimeStudent
然后具有以下函数来继承:
Person::VDescribe
被Student::VDescribe
覆盖,来自Student
Person::VDescribe
没有被覆盖,来自Employee
。Person::VDescribe
没有被覆盖,来自Person
。在这种情况下,Student::VDescribe
会覆盖Person::VDescribe
并且是一个明确的覆盖,因此编译器可以使用它。但是,它警告您有一个替代的继承路径没有通过此覆盖。这个警告在实践中并不是很有用,而且是我经常禁用的少数警告之一。
如果您希望在Student
和Employee
覆盖VDescribe
的情况下编译代码,您实际上也必须在PartTimeStudent
中覆盖它。然后该函数将具有明确的最终覆盖,并且代码将编译得很好。您可以使用限定名称调用一个或两个继承的实现。例如:
void PartTimeStudent::VDescribe()
{
Student::VDescribe();
if (isWorking()) Employe::VDescribe();
}