众所周知,无论派生层次有多深,“虚基类子对象”只会被“最派生”初始化一次在对象构造期间类而不是多次被“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
我的问题是:
如何让vb::f()在上述情况下只被调用一次?
为什么 C++ 的实现者不直接从语言层面支持这种语义?
好的,我尽力让自己明白,但是,我不是英语母语人士,希望您能理解我的意思,感谢您的回复!
最佳答案
当多个派生类从同一个类继承virtualy时,最派生类的对象内部将只有一个该类的子对象。这意味着它只能初始化一次 - 并且由最派生的类完成。
但这只是初始化。但是,这并不意味着只有最派生的类才能访问虚拟基的成员。
你例子中的继承树是这样的:
vb
/ \
A B
\ /
C
如果没有虚拟继承,它会是这样的:
vb vb
| |
A B
\ /
C
A
和 B
在这两种情况下都没有什么特别之处,它们都派生自 vb
并且可以毫无问题地调用它的方法。在第二种情况下,在 C
中调用 vb::f()
是不明确的,并且是一个错误。
关于c++ - 对 C++ 中的虚拟基类感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20030954/