zoukankan      html  css  js  c++  java
  • 条款7:为多态基类声明virtual析构函数

    C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的。其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用。

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class TimeKeeper
     6 {
     7 public:
     8     TimeKeeper();
     9     ~TimeKeeper();
    10 };
    11 TimeKeeper::TimeKeeper()
    12 {
    13     cout << "Construct TimeKeeper" << endl;
    14 }
    15 TimeKeeper::~TimeKeeper()
    16 {
    17     cout << "Destruct TimeKeeper" << endl;
    18 }
    19 
    20 class WristWatch : public TimeKeeper
    21 {
    22 public:
    23     WristWatch();
    24     ~WristWatch();
    25 };
    26 WristWatch::WristWatch()
    27 {
    28     cout << "Construct WristWatch" << endl;
    29 }
    30 WristWatch::~WristWatch()
    31 {
    32     cout << "Destruct WristWatch" << endl;
    33 }
    34 
    35 int main()
    36 {
    37     TimeKeeper* pt = new WristWatch;
    38     delete pt;      // 仅调用TimeKeeper::~TimeKeeper
    39 
    40     return 0;
    41 }

    现在我们将基类的析构函数变为虚析构,代码只改动一行,在~TimeKeeper()前面加上virtual,那么用基类指针释放派生类对象时,就会先调用WristWatch::~WristWatch,然后调用TimeKeeper::~TimeKeeper。

    注意:

    1> 如果在定义一个类时可以确保该类不会作为多态的基类,那么不要为其定义虚析构函数。因为虚函数的实现机制会增大对象的空间(必须保存一个指向vtable的vptr指针,会占用32bit或者64bit的存储空间)。因此,经验是:只有当一个class中至少含有一个virtual函数,才为其定义virtual析构函数。

    2> 不要从non-virtual析构函数的类型继承。

    有时候让一个类带有pure virtual析构函数更便利一些:

    1 class Base
    2 {
    3 public:
    4     virtual ~Base() = 0;    // pure virtual destructor
    5 };
    6 Base::~Base()               // definition
    7 {
    8     
    9 }

    主要有两方面的好处:

    1> 你想拥有一个抽象类(接口),但还没找到任何有用的virtual函数可供使用

    2> 同时解决了多态的析构调用问题。

    但此时你必须注意:必须为这个pure virtual析构函数提供一个实现。因为在析构过程中,编译器会在派生类的析构函数中调用基类的析构函数,如果没定义,则必然发生错误。

     

    总结:

    • 多态基类必须声明一个virtual析构函数。
    • 如果一个类中至少有一个virtual函数,说明该类的目的是作为多态基类存在,它就必须拥有一个virtual析构函数。
    • 如果设计一个类的目的不是作为基类使用,或者是基类但不具有多态性,那么不要声明virtual析构函数。
  • 相关阅读:
    fatal error C1902: 程序数据库管理器不匹配;请检查安装 (zz)
    c++ std string reserve 测试
    2018年长沙理工大学第十三届程序设计竞赛
    2018年东北农业大学春季校赛
    从本质看海明码——海明码的由来
    CodeForces475
    一维背包问题
    2018年长沙理工大学第十三届程序设计竞赛 箱庭的股市
    高精度加法模板
    for,while,do while
  • 原文地址:https://www.cnblogs.com/benxintuzi/p/4525881.html
Copyright © 2011-2022 走看看