使用upcasting时的虚拟析构函数

时间:2011-05-13 12:40:43

标签: c++ inheritance virtual-destructor

每个人都说当至少有一种类方法是虚拟的时,析构函数应该是虚拟的 我的问题是,在使用向上转换时说析构函数应该是虚拟的是不正确的?

class A {
public:

    ~A(){
        cout << "Destructor in A" << endl;
    }
};

class B: public A
{
public:

    ~B(){
        cout << "Destructor in B" << endl;
    }
};

int main()
{
    A* a = new B;
    cout << "Exiting main" << endl;
    delete a;
}

我在这段代码中没有任何虚函数,但是如果我不使我的基础析构函数为虚拟,它就不会调用B析构函数。是的,我知道如果我没有虚函数,使用ucpasting是没有意义的。

谢谢。

5 个答案:

答案 0 :(得分:13)

如果您通过基指针删除派生对象,则需要虚拟析构函数。就是这样,简而言之。

答案 1 :(得分:6)

  

当至少有一个类方法是虚拟的

时,析构函数应该是虚拟的

这是一个经验法则,这是因为当您使用虚函数时,您正在使用运行时多态性并且更有可能遇到这种情况,您需要销毁一个可能属于派生类型的类has是指向其基类子对象的指针。

当您通过在指向基类的指针上使用delete来销毁派生对象时,基类中需要使用虚拟析构函数来避免未定义的行为。这是唯一需要虚拟析构函数的时间,该指南旨在帮助避免出现这种情况。

Herb Sutter提倡指导基类析构函数(即设计为继承的类的析构函数)应为publicvirtualprotected和非{ {1}}。这允许您不希望基类成为继承层次结构中用于删除派生对象的点,并且您希望强制执行此操作不会无意中发生。

当然,如果你有一个纯值类,它不是一个基类,你几乎无法阻止人们从它派生,然后通过指向base的指针删除派生类。

答案 2 :(得分:1)

如果要删除指向派生类的指针,则应该在其中一个类方法为虚拟时声明虚拟析构函数,但指针类型是基类,那么基类在这种情况下必须具有虚拟析构函数或者编译器没有(或者不应该)知道它应该调用什么析构函数(以及它的UB)。

答案 3 :(得分:1)

如果你在派生类析构函数中做了一些有用的事情(内存释放等),那么析构函数应该是virtual

顺便说一句,当class包含virtual方法时,拥有虚拟析构函数是可取(非强制性)。

答案 4 :(得分:0)

这是不正确的:

shared_ptr<A> ptr = make_shared<B>();

正确投射和删除B。请关注@Neil Butterworth的回答。