c++ - 对 C++ 中的虚拟基类感到困惑

标签 c++ virtual

众所周知,无论派生层次有多深,“虚基类子对象”只会被“最派生”初始化一次在对象构造期间类而不是多次被“middle-derived”类调用,这种“虚拟基”的语义是由编译器保证和实现的,然而,当我研究其他成员函数时,除了“构造函数”,我发现,编译器不会将它们视为构造函数,即它不会阻止多次调用虚基类的成员函数,代码如下:

class vb
{
public:
    void f(){cout << "vb::f"<<endl;}

};
class A: public virtual vb
{
public:
    int a;
public:
    void f()
    {
        vb::f();
        cout<<"A::f"<<endl;
    }
};
class B: public virtual vb
{
public:
    int b;
public:
    void f()
    {
        vb::f(); 
        cout<<"B::f"<<endl;
    }
};
class C: public A,public B
{
public:
    int c;
public: 
    void f()
    {
        vb::f();
        A::f();
        B::f();
        cout<<"C::f"<<endl;
    }

};

// test example
int main()
{
    C a;
    a.f();
}

我在Visual Studio 2008中测试了这段代码,结果是:

vb::f

vb::f

A::f

vb::f

B::f

C::f 然而,期望的结果是:

vb::f

A::f

B::f

C::f

我的问题是:

  1. 如何让vb::f()在上述情况下只被调用一次?

  2. 为什么 C++ 的实现者不直接从语言层面支持这种语义?

好的,我尽力让自己明白,但是,我不是英语母语人士,希望您能理解我的意思,感谢您的回复!

最佳答案

当多个派生类从同一个类继承virtualy时,最派生类的对象内部将只有一个该类的子对象。这意味着它只能初始化一次 - 并且由最派生的类完成。

但这只是初始化。但是,这并不意味着只有最派生的类才能访问虚拟基的成员。

你例子中的继承树是这样的:

   vb
  /  \
 A    B
 \   /
   C

如果没有虚拟继承,它会是这样的:

vb  vb
 |   |
 A   B
 \   /
   C

AB 在这两种情况下都没有什么特别之处,它们都派生自 vb 并且可以毫无问题地调用它的方法。在第二种情况下,在 C 中调用 vb::f() 是不明确的,并且是一个错误。

关于c++ - 对 C++ 中的虚拟基类感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20030954/

相关文章:

c++ - 在 WM_MOUSEMOVE 中拖动并绘制边框?

c++ - multimap_intersection 和 multimap_difference 可以类似于 set_intersection 和 set_difference 实现吗?

c++ - 在构造函数中调用纯虚函数会报错

c++ - 异构数组中的元素可以知道它是什么模板类型吗?

c++ - 无法打开包含文件 : 'ntddk.h' : No such file or directory

c++ - 从索引表中进行保序选择的并行算法

c++ - C++中的多行正则表达式模式

c++ - 虚函数的 Vtable 是如何工作的

C++在实现的纯虚拟方法中自动从父抽象类调用检查方法?

C++ 虚函数基返回类型建议