c – 调用虚拟基类的重载构造函数

前端之家收集整理的这篇文章主要介绍了c – 调用虚拟基类的重载构造函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
是否有(实用)的方式来绕过正常(虚拟)构造函数调用顺序?

例:

class A
{
    const int i;

public:
    A()
      : i(0)
    { cout << "calling A()" << endl; }

    A(int p)
      : i(p)
    { cout << "calling A(int)" << endl; }
};

class B
    : public virtual A
{
public:
    B(int i)
      : A(i)
    { cout << "calling B(int)" << endl; }
};

class C
    : public B
{
public:
    C(int i)
      : A(i),B(i)
    { cout << "calling C(int)" << endl; }
};

class D
    : public C
{
public:
    D(int i)
      : /*A(i),*/ C(i)
    { cout << "calling D(int)" << endl; }
};


int main()
{
    D d(42);
    return 0;
}

输出

calling A()
calling B(int)
calling C(int)
calling D(int)

我想要的是:

calling A(int)
calling B(int)
calling C(int)
calling D(int)

如你所见,有虚拟继承涉及,它导致D的构造函数首先调用A的构造函数,但是由于没有提供参数,所以它调用A().有一个const int我需要初始化,所以我有一个问题.

我想做的是隐藏C的继承细节,这就是为什么我正在寻找一种方法来避免在D(和每个派生)构造函数的初始化列表中调用A(i).在这种具体情况下,我可以假设只有C的非虚拟单继承子类(D为1). [/编辑]

[编辑]

Virtual base classes are initialized before any non-virtual base classes are initialized,so only the most derived class can initialize virtual base classes. – James McNellis

这就是要点,我不希望最传统的类调用虚拟基类构造函数.
[/编辑]

考虑以下情况(在上面的代码示例中未表示):

A
 / \
B0  B1
 \ /
  C
  |
  D

我明白为什么当你实例化C时,C必须调用A(歧义)的ctor,但为什么D在实例化D时必须调用

解决方法

不幸的是,你总是必须从最传统的类调用虚拟基类构造函数.

这是因为你说的是​​虚拟基础在从对象的实例派生出来的所有类之间共享.由于构造函数只能在给定的对象实例中调用一次,所以您必须显式调用最传导类中的构造函数,因为编译器不知道有多少类共享虚拟基础(从C编程语言第3版,第15.2.4.1节).这是因为编译器将从最基类的构造函数开始,并且工作到最传导类.直接从虚拟基类继承的类,根据标准,不会调用其虚拟基类构造函数,因此必须显式调用它.

猜你在找的C&C++相关文章