大多数派生 class 如果未实现虚函数则无法编译,但如果一个基 class 未实现虚函数则可以编译
Most derived class cannot compile if virtual function not implemented, but can compile if one base class does not implement the virtual function
我有一个包含 4 个 classes 的 C++ 程序:Person、Student、Employee 和 PartTimeStudent。
Student 和 Employee 均派生自 Person,而 PartTimeStudent 派生自所有 3 个 classes(使其成为最派生的 class)。 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() 时才会发生这种情况。如果其中一个 classes 没有实现 VDescribe(),则编译成功。我仍然收到警告,例如如果我从 Employee 中省略 VDescribe() ,则会出现以下警告:
'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance
请问为什么会出现这种情况?我想知道如果所有 3 classes 实现 VDescribe(),为什么 PartTimeStudent 无法编译,但如果 Student 或 Employee 没有该函数,PartTimeStudent 仍然可以编译。
两次覆盖
想象一下 Student
和 Employee
实现 VDescribe
而 PartTimeStudent
不实现它的 scanario。您希望这段代码的行为如何:
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();
}
我有一个包含 4 个 classes 的 C++ 程序:Person、Student、Employee 和 PartTimeStudent。
Student 和 Employee 均派生自 Person,而 PartTimeStudent 派生自所有 3 个 classes(使其成为最派生的 class)。 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() 时才会发生这种情况。如果其中一个 classes 没有实现 VDescribe(),则编译成功。我仍然收到警告,例如如果我从 Employee 中省略 VDescribe() ,则会出现以下警告:
'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance
请问为什么会出现这种情况?我想知道如果所有 3 classes 实现 VDescribe(),为什么 PartTimeStudent 无法编译,但如果 Student 或 Employee 没有该函数,PartTimeStudent 仍然可以编译。
两次覆盖
想象一下 Student
和 Employee
实现 VDescribe
而 PartTimeStudent
不实现它的 scanario。您希望这段代码的行为如何:
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();
}