C++ 这段代码是否定义了通过基类指针删除派生类的行为?
此代码是否导致定义的行为C++ 这段代码是否定义了通过基类指针删除派生类的行为?,c++,C++,此代码是否导致定义的行为 class A { int x; }; class B { short y; }; class C { double z; }; class D : public A, public B, public C { float bouncy; }; void deleteB(B *b) { delete b; } void is_it_defined() { D *d = new D; deleteB(d);
class A {
int x;
};
class B {
short y;
};
class C {
double z;
};
class D : public A, public B, public C {
float bouncy;
};
void deleteB(B *b) {
delete b;
}
void is_it_defined() {
D *d = new D;
deleteB(d);
B *b = new D; // Is this any different?
delete b;
}
如果没有定义,为什么不呢?如果是,它的定义是什么?为什么?最后,如果它是实现定义的,您能举一个例子说明一个常见的实现可以定义什么样的行为吗?引用:
是否可以执行删除
通过基类进行多态
接口,则它必须行为正常
虚拟的,必须是虚拟的。的确
语言需要它——如果你需要的话
不带标记的多态删除
虚拟析构函数,你召唤
“未定义”的可怕幽灵
行为”
在您的示例中,delete
都是通过基类指针执行的,并产生未定义的行为。标准5.3.5(删除):
在第一个备选方案中(删除
对象),如果
操作数与它的动态
类型,静态类型应为底座
操作数的动态类型的类
静态类型应具有
虚拟析构函数或行为为
未定义
在这里,两个
delete
都作用于静态类型B
,而操作数的动态类型是D
,B
没有虚拟的析构函数,它应该有。这都与虚拟析构函数有关吗?
看看这个:
class A
{
int x;
public:
virtual void fun()
{
return;
}
};
class D : public A
{
float bouncy;
};
void is_it_defined()
{
A *b = new D; // it`s ok!
delete b;
}
你明白了吗?没关系。可以正确删除指针b。
所以,只需要一个虚拟函数来激活多态性。除非类是多态性的,或者包含动态分配的内存,否则析构函数是不相关的。如果有任何理由我们应该能够对注释进行向下投票,这就是它。这里的问题可能是重复的,非类是多态的<代码>B*B=新的D将
B
指针存储在新分配的D
中。如果B
中D
的偏移量不为零,则删除将失败。这里没有定义什么?请注意,在这个例子中,b
的动态类型是b*
,因为b
不是多态的。@b的动态类型是D*。事实上,没有一个类别是多态的。然而,编写的代码实际上期望删除操作。@Sjoerd是的,我猜您期望typeid(*b)
返回D
?-1来表示不正确的内容。您确实需要一个虚拟析构函数。不仅仅是任何旧的虚拟功能。我知道在这种情况下你需要一个虚拟析构函数,但我的问题不是如何让它正常工作。我的问题是,如果你没有做正确的事情,会发生什么?结果是可以预测的吗?当然,我需要一个虚拟析构函数来正确释放资源。但是我有一个问题,为什么我要添加一个虚拟函数,删除操作是可以的。我仍然被对象模型弄糊涂了。所以我只是发布一个问题来讨论。C++不这样。这是一种非常强大的语言,但这不是免费的。C++的缺点之一是错误的代码似乎起作用。您的代码就是一个明显的例子。代码是错误的,但您的编译器无法在编译时进行检查,也没有在运行时进行检查。我们知道这是错误的,因为标准明确指出这是错误的(见icecrime的回复)