没有虚拟构造函数,只有虚拟析构函数

Posted

技术标签:

【中文标题】没有虚拟构造函数,只有虚拟析构函数【英文标题】:No Virtual constructors but virtual destructor 【发布时间】:2012-04-13 00:23:19 【问题描述】:

如果我们没有虚拟构造函数,那么为什么我们有虚拟析构函数?构造函数也可以是虚的吗?

【问题讨论】:

Why do we not have a virtual constructor in C++?的可能重复 @TomaszNurkiewicz:我认为问题是,为什么我们在 C++ 中有虚拟析构函数? 【参考方案1】: 在虚拟构造函数中没有任何意义 - 你声明的正是 类型被创建,并且在编译时是众所周知的。编译器 不需要 [实际上也不能,因为动态调度是基于 关于仅在对象创建后才创建的信息]。 所以没有虚拟构造函数。 虚拟析构函数对于防止内存泄漏很重要,并且 监控系统。假设你有 A* a = new B; [B 继承 来自A],然后是delete a; - 编译器无法 知道aB [在一般情况下],并将调用A's 析构函数 - 如果它不是虚拟的,你可能会遇到内存泄漏, 或其他故障。 使用虚拟析构函数 - 你确保B 的析构函数是 调用,因为 B 对象正在被销毁

【讨论】:

第一点没看懂。请您详细说明一下。 @jhamb:当您调用构造函数时 - 它类似于new MyClass;。创建对象的动态类型静态类型——完全一样,是真正的具体对象。【参考方案2】:

需要虚拟析构函数,因为在销毁时,您并不总是知道要处理的类型:

Base *make_me_an_object()

    if (the_moon_is_full())
        return new Derived();
    else
        return new Base();


int main()

    Base *p = make_me_an_object();
    delete p;

上述程序的main 中的delete 不知道它的p 是指向Base 还是Derived 对象,但是如果Base 析构函数是virtual(因为它应该是),那么delete可以使用*p的vtable找到正确的析构函数。

相比之下,在构建时,您总是知道要创建什么样的对象。 (如果你不知道,那么你可以创建一个知道的工厂或“virtual constructor”。)

【讨论】:

【参考方案3】:
#include<iostream>
using namespace std;
class base 
   protected:
    int a;
;
class derived : public base 

;
int main() 
    base * pointer_of_base = new derived;
    delete pointer_of_base; // this will delete the base calss not the derived


构造函数在我们创建类的对象时被调用一次,所以当我们继承基类时,构造函数只调用一次,所以不需要是虚拟的。

但是当我们从基类的指针访问派生类时,如果我们想删除派生类的对象,我们通过基类的指针删除它,但是delete(pointer_of_base)会调用基类的析构函数但实际的座右铭是删除派生类。因此我们需要析构函数本质上是虚拟的。

【讨论】:

以上是关于没有虚拟构造函数,只有虚拟析构函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在不破坏移动和复制构造函数的情况下声明虚拟析构函数

C++11 虚拟析构函数和移动特殊函数的自动生成

CRT 虚拟析构函数

直接调用(虚拟)析构函数是不是有效?

当删除没有虚拟析构函数的多态对象时会发生啥?

cppyy 模板类实例化没有虚拟析构函数