C++ C++;析构函数-继承上下文中的显式调用

C++ C++;析构函数-继承上下文中的显式调用,c++,memory,destructor,C++,Memory,Destructor,我不确定我的问题有多中肯,但问题来了 我知道我们应该只在堆上分配内存时显式调用析构函数 假设我们有两个类:Animal和Dog,这是Animal的一个子类 Animal a* = new Dog(); //-------Do something here-----// a -> ~Animal(); 同样,让我们假设Animal包含几个动态分配的字段,Dog类添加了几个动态分配的字段 因为狗有更多的字段,调用动物析构函数将导致内存泄漏。这仅仅是糟糕的编程风格,还是

我不确定我的问题有多中肯,但问题来了

我知道我们应该只在堆上分配内存时显式调用析构函数

假设我们有两个类:Animal和Dog,这是Animal的一个子类

    Animal a* = new Dog();
    //-------Do something here-----//
    a -> ~Animal();
同样,让我们假设Animal包含几个动态分配的字段,Dog类添加了几个动态分配的字段

因为狗有更多的字段,调用动物析构函数将导致内存泄漏。这仅仅是糟糕的编程风格,还是我们可以找到解决办法

我想我们需要将指针投射到Dog类型,然后调用析构函数,但是我找不到任何关于如何正确执行此操作的参考

因为狗有更多的字段,调用动物析构函数将导致内存泄漏

如果
动物的析构函数是
虚拟的
,则不会发生这种情况

此外,您不需要调用
~Animal()
。一个例外是,如果您正在编写自己的分配器。通常您会调用
delete a

我知道我们应该只在堆上分配内存时显式调用析构函数

不,不,不,不,不,不。除非在非常特殊的情况下(我所知道的两种情况是placement new和Union),否则永远不会显式调用析构函数


这里需要做的是在指针上调用
delete
。正如rlbond已经说过的,只要基类的析构函数是虚拟的,通过基指针删除就可以了。

您描述的是为什么任何应该被子类化的类都应该有一个虚拟析构函数的原因。出于某种原因,我假设由于不允许使用虚拟构造函数,也不允许使用析构函数。我显然错了。来自Java的背景,对我来说还是有点奇怪。所谓分配器,您指的是一种类似于malloc的定制技术?是的——几乎没有人需要编写自己的分配器。您必须使用一个名为placement
new
的特殊语句。您能给我一个具体的例子,说明我们应该显式调用析构函数吗已编辑:您的编辑回答了我的问题。@SlowTrout如果(a)您使用placement new在单独管理的存储中构造对象,或者(b)该对象是您正在销毁的联合的当前活动成员,则必须显式调用析构函数。第二种情况非常合理。我需要进一步研究第一个案例。非常感谢你的回答。因此,作为对我理解的总结:我只需要确保我将析构函数声明为虚拟并正确设置其行为,“delete”将处理后续调用?@SlowTrout
我需要进一步研究第一个案例
,希望这并不意味着你会使用它(或者更好地说,滥用它)。除了在非常特殊的情况下,几乎没有理由使用placement-new。知道某些事情不会伤害你,但是的,你是完全正确的。我读了一些关于它的书,它应该用于一小部分应用程序。