众所周知,无论派生级别有多深,“虚拟基类子对象”在对象构建过程中仅由“最派生”类初始化一次,而不由“中间派生”多次初始化类,这种“虚拟基础”的语义是由编译器提供担保和实现的,但是,当我研究除“构造函数”之外的其他成员函数时,我发现编译器不会将它们视为构造函数,即,它不执行任何操作。防止多次调用虚拟基类的成员函数,下面是代码:
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 ++的实现者不直接从语言级别支持这种语义?
好的,我会尽力使自己理解,但是,我不是英语的母语人士,希望您理解我的意思,并感谢您的答复!
当一个以上的派生类从同一个类继承虚拟时,该类的一个子对象将在最多派生类的对象内。这意味着它只能被初始化一次-并且它是由最派生的类完成的。
但这仅仅是初始化。但是,这并不意味着只有最派生的类才能访问虚拟库的成员。
您的示例中的继承树如下所示:
vb
/ \
A B
\ /
C
而如果没有虚拟继承,它将是这样的:
vb vb
| |
A B
\ /
C
没什么特别的A
,B
在两种情况下,它们都从a派生而出vb
,可以毫无问题地调用其方法。在第二种情况下,内部C
调用vb::f()
是模棱两可的,并且是一个错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句