多态基类的析构函数应该为虚函数
来源:互联网 发布:java中的构造器是什么 编辑:程序博客网 时间:2024/06/08 06:51
多态基类的析构函数应该为虚函数
#include<iostream>using namespace std;class CBird{public: CBird() { cout << "CBird constructor." << endl; }; ~CBird() { cout << "CBird destructor." << endl; }; virtual void fly() { cout << "CBird fly." << endl; };};class CLark : public CBird{public: CLark() { cout << "CLark constructor." << endl; }; ~CLark() { cout << "CLark destructor." << endl; }; void fly() { cout << "CLark fly." << endl; }};int main(){ CBird * pBird = new CLark(); pBird->fly(); delete pBird; return 0;}
CBird作为基类描述鸟类的一般行为和属性,因为不同鸟类的飞行特点不同,所以基类CBird将fly()声明为virtrual,希望派生类重写(overriding)该方法。CLark(lark:百灵鸟)继承自CBird,并重写了fly()。
main函数中基类CBird类型指针指向派生类CLark类型对象,并以基类指针调用fly方法,根据c++的多态特性,实际调用的是CLark的fly方法。
可以看到“pBird->fly();”的确调用了派生类CLark的fly方法。但对象析构时只调用了基类CBird的析构函数,却没有调用派生类CLark的析构函数,这种现象叫做“部分析构”。
产生这个问题的原因是:当一个派生类对象通过一个基类指针删除,并且这个基类的析构函数是非虚的,c++将不会调用整个析构函数链,结果是未定义的。所以这种情况下,只调用了基类CBird的析构函数,对象的派生部分并没有被销毁。
解决办法就是将多态基类的析构函数设置为virtual。多态基类指的是基类中至少存在一个virtual函数,具有virtual函数的类也就是想当爹(base class)的类,这样的类简称为多态基类。将CBird的析构函数设置为virtual,再看程序的输出结果。
并不是所有c++类都应该将析构函数设置为virtual。只有具有virtual函数的多态基类(或者其它想当base class的类)才应该将析构函数设置为virtual,对于普通的类则无必要。因为虚函数的实现要求对象携带额外信息,也就是维护一个指向虚函数表的指针vptr(virtual table pointer),vptr指向虚函数表vtbl(virtual table)。当调用一个对象的虚函数时,就会通过vptr找到vtbl,在vtbl中寻找正确的函数指针调用。由于vptr的加入,导致对象大小增加。所以对于非多态基类,没必要将析构函数声明为virtual以带来额外负担。这同时引出另外一条准则,如果一个类的析构函数非虚,那就说明它不想当爹,程序员要顶住诱惑,拒绝继承它,即使它“出身名门”,比如标准库中的string等等。
另外,有时还会将析构函数设置为纯虚函数(pure virtual),拥有纯虚函数的类变为抽象基类(abstract class),抽象基类不能被实例化。如果某个class只希望作为base class(不希望被实例化),但是又没有一个纯虚函数,而base class应该有一个virtual析构函数,那么此时就可以将析构函数设置为纯虚函数。
必须为纯虚析构函数提供定义,否则会出现Link错误。因为析构函数的运作方式是,最深层派生(most derived)的那个class其析构函数最先被调用。然后是其每一个base class的析构函数被调用。
- 多态基类的析构函数应该为虚函数
- 多态基类的析构函数应该为虚函数
- 多态基类的析构函数应该为虚函数
- 条款7:多态基类的析构函数应该为虚函数
- 构造函数不能为虚函数,析构函数能并且应该为虚函数
- 析构函数是否应该标记为虚函数
- 什么情况下,类的析构函数应该声明为虚函数?
- 什么情况下,类的析构函数应该声明为虚函数?
- 什么情况下,类的析构函数应该声明为虚函数
- 什么情况下,类的析构函数应该声明为虚函数?
- 析构函数是否必须为虚函数?什么情况下才应该定义析构函数为虚函数?
- c++(重载、覆盖、隐藏)&&什么情况下,类的析构函数应该声明为虚函数?为什么?
- 构造函数、析构函数为虚函数的区别
- 关于基类的析构函数应不应该为virtual
- 析构函数设为虚函数的作用
- 析构函数定义为虚函数的好处
- C++ 析构函数设为虚函数的好处
- 将 析构函数 声明为 虚函数 的必要性
- Java map排序(TreeMap,LinkedHashMap)
- 哈夫曼编码译码的应用(0.9a版)
- CDN(内容分发网络)技术原理
- LeetCode-Valid Number
- php 远程上传(CURL)
- 多态基类的析构函数应该为虚函数
- C++虚继承
- Android 自定义View
- Linux内核模块实例
- CocoaPods安装和使用教程
- iOS画图 上下文栈的使用
- ODC(Orthogonal Defect Classification)简介
- 《Java程序设计》第16周周四:GUI编程及文件对话框的使用~作业
- 消息队列的读写