2

在 C# 中跨继承链接构造函数非常方便且有用。在 C++ 中实现类似功能的最佳方法是什么?这就是我想表达的:

struct A
{
    A(int p)
    {
        i = p;
    }

    int i;
};

struct B : virtual A
{
    B(int q) : A(q)
    {
    }
};

struct C : virtual B
{
    C(int r) : B(r) // call B::B() which in turn would call A::A()
    {
    }
};

有任何想法吗?

干杯,查理。

4

2 回答 2

3

最派生类(即C)负责构造所有虚拟基类。因此,C可以同时初始化AB

C(int r) : A(r), B(r)

请注意,虚拟基类在任何非虚拟基类之前初始化。没有办法B初始化虚拟基类A

你可以一起破解一些东西,例如通过使虚拟基础A默认可构造然后给它一个B可以在其构造函数中调用的“初始化”方法,但这样做可能会被证明是危险的。当B为基类子对象调用构造函数时B,它无法知道C虚拟派生自的其他基类是否A已经初始化(并且可能已经使用过A),或者它是唯一将要执行的类尝试初始化A.

于 2012-08-13T18:23:16.757 回答
2

在 C++ 中,虚拟继承需要最派生类型的构造函数显式调用所有虚基的构造函数:

C( int r ) : A(r), B(r) {}

虽然您已明确声明需要虚拟继承,但使用虚拟继承并不常见,因此您可能需要解释用例。可能存在不需要这个的替代方案,因此将允许构造函数的链接


如果您想知道最派生类型需要调用构造函数,原因是virtual继承意味着完整对象中只有一个这样的基。现在,如果您考虑可能的关系:

struct base { base( int x ); /*...*/ };
struct d1 : virtual base {
   d1() : base(1) {}
// ...
};
struct d2 : virtual base {
   d2() : base(2) {}
// ...
};
struct final : d1, d2 {};

应该将什么值传递给baseinside的单个实例的构造函数final?两个不同的继承路径传递了冲突的值,但只有一个对象需要初始化。即使不同的调用没有冲突,使用单独的编译模型,编译器也无法知道这一点,因此唯一的选择是完整的对象决定如何初始化虚拟基。

于 2012-08-13T18:24:12.093 回答