C++ 通过基初始化派生类

C++ 通过基初始化派生类,c++,multiple-inheritance,C++,Multiple Inheritance,考虑: struct V { V(int i) { std::cout << "initialized v" << '\n'; } }; struct A { A() { std::cout << "initialized a" << '\n'; } }; struct B : virtual V, virtual A { B(int i) :V{i} {

考虑:

struct V {
    V(int i) {
        std::cout << "initialized v" << '\n';
    }
};

struct A {
    A() {
        std::cout << "initialized a" << '\n';
    }
};

struct B : virtual V, virtual A {
    B(int i) :V{i} {
        std::cout << "initialized b" << '\n';
    }
};

class C : virtual V, virtual A {
public:
    C(int i) : V{i} {
        std::cout << "initialized c" << '\n';
    }
};

class D : virtual public B, virtual public C {
public:
    D(int i, int j) :V{i}, B{i}, C{j} {
        std::cout << "initialized d" << '\n';
    }
};
但是如果我使用工厂,像这样:

int main() {
    D* d = new D{3,3}; //ok
    B* b = new D{3,3}; //ok
    C* c = new D{3,3}; //undefined
    delete d;
    delete b;
    delete c;

}
C* factory() {
    return new D{3,3};
}

int main() {
    factory(); //ok
}
当我在main()中通过C初始化D时,我不明白为什么它会导致未定义的行为,但当我使用其他函数时,它可以正常工作。C怎么了?它和B不一样吗


编辑:所以我的代码运行良好,正如我认为它应该。如果我的代码没有问题,我的开发环境有问题吗?我正在将最新的mingw-w64与eclipse CPP一起使用。

您在所有错误的地方寻找不确定性

delete b;
delete c;
这两行都调用未定义的行为,通过指向基类(a
B*
C*
)的指针删除派生类对象(a
D
),而不使用虚拟析构函数。给他们一个(例如,通过将
virtual~V()=default;
添加到
V
),崩溃应该会消失


这就是为什么验证您在这里发布的代码是否确实再现了编译和运行时看到的崩溃非常重要的原因。如果一开始就有完整的代码,可能有人会在不到5分钟内发现问题。相反,我们花了45分钟试图重现问题。

您是如何检测到未定义的行为的?您的代码似乎编译并运行良好()。@dasblinkenlight:您怎么知道它不是UB?因为什么?因为“它成功了”一次?这是一个非常糟糕的启发式C++ +…,我也没有看到任何UB在这个代码。在构造和销毁具有多个继承和虚拟基础的对象时,有一些复杂的规则可以导出基本转换,但这个代码不执行任何操作。@ DasBLink NeLink:我只是想指出,不幸的是,“编译和运行良好”不是C++的好度量。如果你想说看看代码,它是正确的,没有问题,然后罚款。。。相反,因为编译和(显然)运行没有问题是一条通往C++的痛苦之地的路径(因为有很多编译和“运行良好”的代码,而不是UB).@ KuramaYoko是因为虚拟基类的虚拟继承而强制的。