类型需要虚析构函数的另外一个特征 是该类型具有指针成员或引用成员。如果有指针成员和引用成员,则该类型通常需要实现析构函数以及拷贝操作。

通常,一个实现了析构函数的类型同时也需要实现拷贝构造函数与拷贝复制函数。

作为一个经验法则:

如果你有一个带有虚函数功能的类,则它需要一个虚析构函数,原因如下:

1. 如果一个类有虚函数功能,它经常作为一个基类使用。

2.如果它是一个基类,它的派生类经常使用new来分配。

3.如果一个派生类对象使用new来分配,并且通过一个指向它的基类的指针来控制,那么它经常通过一个指向它的基类的指针来删除它(如果基类没有虚析构函数,结果将是不确定的,实际发生时,派生类的析构函数永远不会被调用)。

基类有虚析构函数的话,最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。

现在还不明白的,作为保护性的析构函数的作用何在?这里有一种解释http://blog.csdn.net/huzzyy/article/details/2562804  。理解了,以后再补充。

对于声明为保护的析构函数,网上有这样的解释:

1、如果一个类被继承,同时定义了基类以外的成员对象,且基类析构函数不是virtual修饰的,那么当基类指针或引用指向派生类对象并析构(例如自动对象在函数作用域结束时;或者通过delete)时,会调用基类的析构函数而导致派生类定义的成员没有被析构,产生内存泄露等问题。虽然把析构函数定义成virtual的可以解决这个问题,但是当其它成员函数都不是virtual函数时,会在基类和派生类引入vtable,实例引入vptr造成运行时的性能损失。如果确定不需要直接而是只通过派生类对象使用基类,可以把析构函数定义为protected(这样会导致基类和派生类外使用自动对象和delete时的错误,因为访问权限禁止调用析构函数),就不会导致以上问题。2、保证对象只生成在堆上。看见一篇博文,问到了和我类似的问题,摘录如下:我看到有些程序中,将构造函数,析构函数声明为私有和保护的,那么对象如何创建?已经不能从外部调用构造函数了,但是对象必须被构造,应该如何解决,麻烦大家帮忙说明,关于构造,析构函数声明为私有和保护时的用法,谢谢了! 从语法上来讲,一个函数被声明为protected或者private,那么这个函数就不能从“外部”直接被调用了。对于protected的函数,子类的“内部”的其他函数可以调用之。而对于private的函数,只能被本类“内部”的其他函数说调用。

语法上就是这么规定的,你肯定也知道的咯。那么为什么有时候将构造函数或者析构函数声明为protected的或者private的?

通常使用的场景如下:1。如果你不想让外面的用户直接构造一个类(假设这个类的名字为A)的对象,而希望用户只能构造这个类A的子类,那你就可以将类A的构造函数/析构函数声明为protected,而将类A的子类的构造函数/析构函数声明为public。例如:class A{ protected: A(){}  public: ....};calss B : public A{ public: B(){}  ....};

A a; // errorB b; // ok

2. 如果将构造函数/析构函数声明为private,那只能这个类的“内部”的函数才能构造这个类的对象了。这里所说的“内部”不知道你是否能明白,下面举个例子吧。class A{private:    A(){  }    ~A(){ }

public:    void Instance()//类A的内部的一个函数    {        A a;    }};上面的代码是能通过编译的。上面代码里的Instance函数就是类A的内部的一个函数。Instance函数体里就构建了一个A的对象。但是,这个Instance函数还是不能够被外面调用的。为什么呢?如果要调用Instance函数,必须有一个对象被构造出来。但是构造函数被声明为private的了。外部不能直接构造一个对象出来。A aObj; // 编译通不过aObj.Instance();但是,如果Instance是一个static静态函数的话,就可以不需要通过一个对象,而可以直接被调用。如下:class A{private:    A():data(10){ cout << "A" << endl; }    ~A(){ cout << "~A" << endl; }

    public:    static A& Instance()    {        static A a;        return a;    }

    void Print()    {        cout << data << endl;    }

private:    int data;};

A& ra = A::Instance();ra.Print();

上面的代码其实是设计模式singleton模式的一个简单的C++代码实现。

还有一个情况是:通常将拷贝构造函数和operator=(赋值操作符重载)声明成private,但是没有实现体。这个的目的是禁止一个类的外部用户对这个类的对象进行复制动作。细节请看《effective C++》里面的一个条款。具体哪个条款不记得了。你自己去找吧。

转载于:https://www.cnblogs.com/kanego/archive/2011/10/03/virtual_destructor.html

C++ 虚析构函数相关推荐

  1. C++继承中构造函数、析构函数调用顺序及虚析构函数

    首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就可以调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  2. unique函数_C++智能指针2:(虚?)析构函数(标准与实现的差异)

    只要是有良心的 C++ 教材,总是会苦心孤诣地告诫初学者,在继承关系中,应该把父类的析构函数定义成虚函数.这已然成为一条铁律,如果违背,不仅有内存泄漏的风险,在多继承情况下甚至会出现未定义行为.因此, ...

  3. C++对象模型7——类的成员函数、反汇编虚析构函数、RTTI、多态的开销

    一.类成员函数 class test { public:void myfunc(){}virtual void vfunc() {}static void sfunc() {} };void myfu ...

  4. C++编程进阶2(编译器在类内默认生成的函数讨论以及纯虚析构函数)

    三.编译器默认提供的类内函数讨论 1.当写下一个空类时,编译器会在必要的时候默认提供四个函数:构造.拷贝构造.operator=和析构函数,而且都是public的 class Empty{ }; 上述 ...

  5. 为什么一般要定义析构函数为虚析构函数

    没有使用虚析构函数可能会出现的问题: #include <iostream> #include <string> using namespace std;class A { p ...

  6. C++继承中析构函数 构造函数的调用顺序以及虚析构函数

    首先说说构造函数.大家都知道构造函数里就能够调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就能够调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  7. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  8. 多态基类与虚析构函数

    假设我们有一个基类A,很不幸的,A的析构函数是一个non-virtual.同时我们有一个派生类B,它派生自A. 我们定义了一个A类型指针,它指向的实际对象是B: A * ptr = new B; 然后 ...

  9. 【c++】28.虚析构函数、纯虚函数

    1.虚函数:在类的成员函数前面加virtual关键字的函数: 一般把虚函数定义在public区,方便在主函数中调用 如果一个类有一个虚函数,则该类就有一个虚函数列表,所有该类的对象都共享这个虚函数表: ...

最新文章

  1. mysql 5.1默认缓存_mysql的innodb数据库引擎详解
  2. Python_基础_6
  3. druiddatasource配置_Springboot属性注入 Java配置和Value配置
  4. Navicat工具里的empty table和truncate table的区别
  5. windows 8文件操作帮助类FileHelper
  6. PHP在线无人值守源码交易网站源码,集成支付宝微信接口
  7. 我的YUV播放器MFC小笔记:解析文件名称
  8. JavaScript学习篇(4)
  9. 搜狗输入法linux词库导入,Fedora 20下 ibus 导入搜狗词库的正确做法
  10. RCC_APB2Periph_ALL 哪儿里去了?
  11. 英语听力下载《走遍美国》
  12. Source Insight等宽字体及对齐设置方式
  13. 上交大计算机科学与技术,上海交通大学计算机科学与工程系(CSE)
  14. 用js将HTML文本导出生成word文档
  15. 微营销视频教程免费在线观看
  16. 一些程序设计常识(bushi)
  17. new DecimalFormat(0.##)与new DecimalFormat(0.00)的区别
  18. 39.超市微信促销活动5
  19. 当应用出现 access violation at address in module时
  20. 实现图片模糊(背景虚化)

热门文章

  1. 软件测试用python一般用来做什么-python软件测试
  2. python流程图-python中的图表渲染(流程图可视化)
  3. python贴吧爬虫-Python爬虫——抓取贴吧帖子
  4. python编程 入门到实践-Python编程入门到实践(二)
  5. 学python先学什么-学Python之前,什么最重要?
  6. pythonurllib模块-Python中的urllib模块使用详解
  7. pythonapp下载-QPythonapp下载
  8. python乘法口诀表-用python打印99乘法口诀表
  9. python在会计中的应用-Python会计数据分析
  10. python语言入门m-Python2 教程