【问题标题】:wrong constructor called for virtual base class of virtual base class为虚拟基类的虚拟基类调用了错误的构造函数
【发布时间】:2021-04-15 01:47:36
【问题描述】:

我在使用分布在多个文件中的非常复杂的类结构的构造函数时遇到问题。每个类都有一个不带参数的公共默认构造器和一个带参数的受保护构造器。任何派生类的每个构造函数都使用参数调用其父类的受保护构造函数。下面的例子对于结构中的所有派生类都是一样的(父类的数量可能不同)。

文件示例.h:

class SomeDerivedClass : virtual public SomeParentClass, virtual public SomeOtherParentClass {
public:
    SomeDerivedClass();
protected:
    SomeDerivedClass(int value);
}

文件example.cpp:

SomeDerivedClass::SomeDerivedClass() : SomeParentClass(0), SomeOtherParentClass(0) {
    printf("SomeDerivedClass\n");
}
SomeDerivedClass::SomeDerivedClass(int value) : SomeParentClass(value), SomeOtherParentClass(value) {
    printf("SomeDerivedClass(%d)\n", value);
}

当我构造一个类时,所有的直接虚拟父对象都是用带参数的受保护构造函数构造的。但是即使父母的受保护构造函数也应该调用它自己的虚拟父母的受保护构造函数,祖父母总是使用默认构造函数构造。

小例子:

#include <stdio.h>

class Base {
public:
  Base() { printf("Base()\n"); }
  ~Base() {}
protected:
  Base(int value) { printf("Base(%d)\n", value); }
};

class Derived1 : virtual public Base {
public:
  Derived1() : Base(0) { printf("Derived1()\n"); }
  ~Derived1() {}
protected:
  Derived1(int value) : Base(value) { printf("Derived1(%d)\n", value); }
};

class Derived2 : virtual public Derived1 {
public:
  Derived2() : Derived1(0) { printf("Derived2()\n"); }
  ~Derived2() {}
protected:
  Derived2(int value) : Derived1(value) { printf("Derived2(%d)\n", value); }
};

int main() {
  Derived2* NewDerived2 = new Derived2();
}

结果:

Base()
Derived1(0)
Derived2()

【问题讨论】:

  • 请提供一个最小(简化)示例来说明问题。
  • 在 C++ 中,所有“虚拟父母”总是“直接”的。没有“虚拟祖父母”,这就是我认为您正在做的事情。这就是虚拟继承的工作原理。虚拟继承的类总是最派生类的父类,它直接继承它们,无论是否显式声明。 C++ 不能以任何其他方式工作。
  • @SamVarshavchik 是的,在最小示例中可以正常工作。我已经在实际问题上尝试过,我得到“Base 不是 Derived2 的直接或虚拟基础”
  • @SamVarshavchik 我的意思是:从 Derived2 调用 Base 构造函数在最小示例中可以正常工作。在真正的问题上,我收到错误“Base is not a direct or virtual base of Derived2”
  • 在这种情况下,您未能显示“真正的问题”,因为显示的代码不会产生此编译错误,而是实际运行,我的评论实际上完美地解释了为什么结果是这样的。不太可能有人可以帮助您解释甚至没有显示的代码问题,而是仅显示其他一些工作代码。

标签: c++ c++11 inheritance multiple-inheritance virtual-inheritance


【解决方案1】:

答案由 Sam Varshavchik 在 cmets 中给出。

将参数从每个构造函数传递给它的直接父级的概念是处理问题的错误方法。

我有错误的印象,我只能访问每个班级的直接父母。 Sam Varshavchik 的评论帮助我看到了真正的问题并在正确的地方寻找它。在众多类之一中,有一个非虚拟继承使得无法访问基类的构造函数。

【讨论】:

    猜你喜欢
    • 2011-09-21
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    • 2012-05-19
    相关资源
    最近更新 更多