博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
条款7:为多态基类声明virtual析构函数
阅读量:6487 次
发布时间:2019-06-24

本文共 1628 字,大约阅读时间需要 5 分钟。

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

1 #include 
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 TimeKeeper21 {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::~TimeKeeper39 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 Base2 {3 public:4     virtual ~Base() = 0;    // pure virtual destructor5 };6 Base::~Base()               // definition7 {8     9 }

主要有两方面的好处:

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

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

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

 

总结:

  • 多态基类必须声明一个virtual析构函数。
  • 如果一个类中至少有一个virtual函数,说明该类的目的是作为多态基类存在,它就必须拥有一个virtual析构函数。
  • 如果设计一个类的目的不是作为基类使用,或者是基类但不具有多态性,那么不要声明virtual析构函数。

 

转载于:https://www.cnblogs.com/benxintuzi/p/4525881.html

你可能感兴趣的文章
checkmysql.sh
查看>>
Android按键添加和处理的方案【转】
查看>>
如何让 Xcode 在读写上提速100倍?
查看>>
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password)
查看>>
SAP FICO 凭证导入接口 数据xml格式
查看>>
Jupyter Notebook快捷键
查看>>
概率运算中C(k,n)是怎么算的啊? 比如C(6,3)等于几?怎么来的.
查看>>
ES6中Set集合(与java里类似)
查看>>
Python的全局和局部变量
查看>>
快递企业如何完成运单订阅消息的推送
查看>>
shell特殊符号cut命令 sort_wc_uniq命令 tee_tr_split命令 shell特殊符号
查看>>
使用vcastr22.swf做flash版网页视频播放器
查看>>
currentThread()方法返回代码段正在被哪个线程调用
查看>>
java 执行command
查看>>
修改远程桌面连接端口3389,RDP-Tcp的portnumber要用十六进制修改
查看>>
8-Highcharts曲线图之对数直线图
查看>>
Leetcode: Shuffle an Array
查看>>
JSP 页面传值方法总结
查看>>
再探canvas(小球实例)
查看>>
(原)torch中提示Unwritable object <userdata> at <?>.callback.self.XXX.threads.__gc__
查看>>