通过 bases 初始化 derived 类
Initializing derived classes through bases
考虑:
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';
}
};
如果我在 main() 中初始化 D,像这样:
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一样吗?
编辑:所以我的代码在 this demo 上运行良好,正如我认为的那样。如果我的代码没有问题,是不是我的开发环境有问题?我正在使用最新的 mingw-w64 和 eclipse CPP。
你在所有错误的地方寻找不确定性。
delete b;
delete c;
这两行调用未定义的行为,通过删除派生的 class 对象(D
)和指向基 class 的指针(B*
或 C*
) 没有虚拟析构函数。给他们一个(例如,将 virtual ~V() = default;
添加到 V
),崩溃应该会消失。
这就是为什么验证您 post 此处的代码实际上 重现了 您在编译和 运行 时看到的崩溃的原因。如果一开始就有完整的代码,有人可能会在不到 5 分钟的时间内发现问题。相反,我们花了 45 分钟试图重现该问题。
考虑:
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';
}
};
如果我在 main() 中初始化 D,像这样:
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一样吗?
编辑:所以我的代码在 this demo 上运行良好,正如我认为的那样。如果我的代码没有问题,是不是我的开发环境有问题?我正在使用最新的 mingw-w64 和 eclipse CPP。
你在所有错误的地方寻找不确定性。
delete b;
delete c;
这两行调用未定义的行为,通过删除派生的 class 对象(D
)和指向基 class 的指针(B*
或 C*
) 没有虚拟析构函数。给他们一个(例如,将 virtual ~V() = default;
添加到 V
),崩溃应该会消失。
这就是为什么验证您 post 此处的代码实际上 重现了 您在编译和 运行 时看到的崩溃的原因。如果一开始就有完整的代码,有人可能会在不到 5 分钟的时间内发现问题。相反,我们花了 45 分钟试图重现该问题。