使用虚拟继承时强制调用基本构造函数,尽管它永远不会被调用?

Forced to call the base constructor when using virtual inheritance although it will never be called?

我有一个 class Base 它有一个参数化的构造函数和两个 classes Middle1Middle2 实际上继承自 Base(为了解决菱形问题)。另外,classFoo继承自Middle1Middle2

Foo 现在显式调用 Base 构造函数并传递参数。

class Base
{
private:
    int value;
protected:
    Base(int& value) { this->value = value; }
};

class Middle1 : virtual public Base
{
protected:
    Middle1() { }
};

class Middle2 : virtual public Base
{
protected:
    Middle2() { }
};

class Foo : public Middle1, public Middle2
{
public:
    Foo(int& value) : Base(value) { }    
};

然而,代码无法编译,因为 Base 缺少默认构造函数,因此 Middle1 和 Middle2 没有可调用的默认构造函数,但需要一个可以被 Foo 调用的构造函数。

当然,我现在也可以更改 Middle1 和 Middle2 的构造函数来调用 Base 的构造函数:

Middle1(int& value) : Base(value) { }
//...
Middle2(int& value) : Base(value) { }
// and then change my constructor of Foo:
Foo(int& value) : Base(value), Middle1(value), Middle2(value) { }  

然而,它看起来相当笨拙 - 特别是考虑到由于虚拟继承, Base 构造函数将永远不会被 Middle1 或 Middle2 调用(它们不打算被初始化,即基本上是抽象的 class es)。因此,必须将参数引入到 Middle1 和 Middle2 的构造函数中似乎毫无用处。

有没有其他方法可以编译上述代码而不必在 Middle1 和 Middle2 中引入参数化构造函数?

在虚拟继承中,最派生的 class 必须 直接 调用其所有祖先构造函数。由于 Base 没有默认构造函数,如果 Middle1()Middle2() 不能将 int& 传递给 Base(),则它们无法编译。

但是,在您显示的代码中,Base() 没有理由引用 int。改为按值传递,然后 Middle1()Middle2() 可以将 0 传递给 Base():

class Base
{
private:
    int value;
protected:
    Base(int value = 0) { this->value = value; }
};

class Middle1 : virtual public Base
{
protected:
    Middle1() { }
};

class Middle2 : virtual public Base
{
protected:
    Middle2() { }
};

class Foo : public Middle1, public Middle2
{
public:
    Foo(int value) : Base(value) { }    
};

不过,我建议改为传递指针(或 std::optional):

class Base
{
private:
    int value;
protected:
    Base(int* avalue = nullptr) { if (avalue) this->value = *avalue; }
};

class Middle1 : virtual public Base
{
protected:
    Middle1() { }
};

class Middle2 : virtual public Base
{
protected:
    Middle2() { }
};

class Foo : public Middle1, public Middle2
{
public:
    Foo(int& value) : Base(&value) { }    
};