这是否存在此代码的已定义行为,该行为通过基类指针删除派生类?

时间:2010-11-14 18:18:38

标签: 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);

    B *b = new D;  // Is this any different?
    delete b;
}

如果没有定义,为什么不呢?如果是,它定义的是什么以及为什么?最后,如果它的实现定义了,你能举例说明一个常见的实现可能会定义行为吗?

3 个答案:

答案 0 :(得分:6)

引用Herb Sutter

  

如果可以执行删除   多态地通过基类   接口,然后它必须表现   虚拟而且必须是虚拟的。确实,   语言需要它 - 如果你   多态删除没有   虚拟析构函数,你召唤   可怕的幽灵“未定义   行为”。

在您的示例中,delete都是通过基类指针执行的,并产生未定义的行为。标准5.3.5(删除):

  

在第一种选择中(删除   object),如果是静态类型的   操作数与其动态不同   类型,静态类型应为基础   操作数的动态类型的类   而静态类型应该有一个   虚拟析构函数或行为是   未定义

此处,delete对静态类型B起作用,而操作数的动态类型为D

答案 1 :(得分:0)

B没有虚拟析构函数,它应该有。

答案 2 :(得分:-1)

是否关注虚拟析构函数? 看看这个:

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可以正确删除。 所以,只需要一个虚拟函数来激活多态。