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的回复)