范围界定是访问虚拟功能的合法方式吗?

Is scoping a legitimate way to access virtual functions?

我有一个包含 4 个 classes 的 C++ 程序:Person、Student、Employee 和 PartTimeStudent。

Student 和 Employee 均派生自 Person,而 PartTimeStudent 派生自所有 3 个 classes(使其成为最派生的 class)。所有 classes 都有一个名为 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()。我想知道的是,这是访问虚函数的合法方式吗?这是可以接受还是不鼓励的做法?

是的,这是一种绕过动态调度并调用特定版本的虚函数而不是其最终覆盖程序的完全合法的方法。

但是,我通常会觉得在 class 的 外部 看到这样的代码很奇怪,我会检查是否有可能设计问题或误解。通常,此类代码在 内部 class 本身用于调用函数的覆盖版本(通常来自覆盖程序)。

这是非虚拟 调用这些函数的合法方式。没有普遍禁止,但在构造函数中执行此操作时必须小心(因为你的基础 类 是 virtual)。您必须确定命名的基础子对象已经存在。对于非虚拟基础 类,这不是问题,因为它们是按顺序构建的。