我有一个包含4个类的C ++程序:Person,Student,Employee和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
{
...
virtual void VDescribe();
...
};
注意:在上面的代码片段中,我省略了构造函数,析构函数和成员变量,因为它们与问题无关。
另外,我有以下代码,其中通过指针创建和访问PartTimeStudent对象。我使用作用域来调用PartTimeStudent对象中不同子对象的VDescribe()函数。
void DoTest()
{
PartTimeStudent* pPTS = new PartTimeStudent("John", 23, "NTU", "Seven-Eleven");
pPTS->VDescribe();
pPTS->::Person::VDescribe();
pPTS->::Student::VDescribe();
pPTS->::Employee::VDescribe();
}
代码编译成功,我可以调用不同版本的VDescribe()。我想知道的是,这是一种访问虚拟功能的合法手段吗?这是可接受的还是气馁的做法?
答案 0 :(得分:4)
是的,这是绕过动态调度和调用虚拟函数的特定版本而不是最终覆盖的完全合法方式。
但是,我通常会发现在类的外部上看到这样的代码很奇怪,我会检查是否存在设计问题或误解。通常,此类代码在内部类本身中使用,以调用函数的重写版本(通常来自覆盖者)。
答案 1 :(得分:2)
这是非虚拟调用这些函数的合法方式。没有一般禁止,但在构造函数中执行此操作时必须小心(因为您的基类是virtual
)。您必须确定已命名的基础子对象已存在。对于非虚拟基类,这不是问题,因为它们是按顺序构建的。