代码之家  ›  专栏  ›  技术社区  ›  Omnifarious

此代码是否有通过基类指针删除派生类的已定义行为?

c++
  •  2
  • Omnifarious  · 技术社区  · 15 年前

    此代码是否导致定义的行为?

    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 回复  |  直到 15 年前
        1
  •  6
  •   icecrime    15 年前

    引用 Herb Sutter :

    如果可以删除 多态地通过基类 接口,那么它必须 虚拟的,必须是虚拟的。的确, 语言需要它-如果你 不带 虚拟毁灭者,你召唤 可怕的“未定义”幽灵 行为”。

    在你的例子中,两者 delete 通过基类指针执行并产生未定义的行为。标准5.3.5(删除):

    在第一个备选方案中(删除 对象), 如果 操作数与其动态操作数不同 类型,静态类型应为 操作数动态类型的类 静态类型应具有 虚拟析构函数 未定义 .

    这里,两个 删除 作用于静态类型 B 而操作数的动态类型是 D .

        2
  •  0
  •   peoro    15 年前

    B 没有 事实上的 析构函数,应该有。

        3
  •  -1
  •   Omnifarious    15 年前

    这都是关于虚拟析构函数的吗? 看看这个:

    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可以正确删除。 所以,只需要一个视觉功能来激活多态性。