3

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

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 毫无意义。

谢谢你。

4

5 回答 5

13

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

于 2011-05-13T12:48:30.797 回答
7

当至少一个类方法是虚拟的时,析构函数应该是虚拟的

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

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

Herb Sutter提倡基类析构函数(即设计为从其继承的类的析构函数)应该是publicand virtualor protectedand non-的指导方针virtual。这允许您不打算将基类作为用于删除派生对象的继承层次结构中的一个点,并且您希望强制这种情况不会无意发生。

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

于 2011-05-13T12:59:00.197 回答
1

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

于 2011-05-13T12:43:50.120 回答
1

virtual如果您在派生类析构函数中做一些有用的事情(内存释放等),则应该使用析构函数。

顺便说一句,当 a包含方法时,建议(不是强制性的)使用虚拟析构函数。classvirtual

于 2011-05-13T12:48:11.903 回答
0

这是不正确的:

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

确实向上转换并正确删除B。只需遵循@Neil Butterworth 的回答即可。

于 2011-05-13T13:00:59.283 回答