(C++)浅谈多态基类析构函数声明为虚函数
主要内容:
1、C++类继承中的构造函数和析构函数
2、C++多态性中的静态绑定和动态绑定
3、C++多态性中析构函数声明为虚函数
1、C++类继承中的构造函数和析构函数
在C++的类继承中,
建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推;
析构对象时,其顺序正好与构造相反;
具体参考文章:http://www.cnblogs.com/AndyJee/p/4575385.html
2、C++多态性中的静态绑定和动态绑定
对象的静态类型:对象在声明是采用的类型,在编译期确定;
对象的动态类型:当前对象所指的类型,在运行期决定,对象的动态类型可以更改,但静态类型无法更改。
静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
具体参考文章:http://www.cnblogs.com/AndyJee/p/4575670.html
3、C++多态性中基类析构函数声明为虚函数
先来看几段程序例子:
- 将基类析构函数声明为虚函数
#include <iostream>
using namespace std; class Person{
public:
virtual ~Person(){ //declare destructor as a virtual function
cout << "Person::~Person()" << endl;
}
}; class Student : public Person{
public:
~Student(){ // virtual or not is OK
cout << "Student::~Student()" << endl;
}
}; int main(){
Person *pt1 = new Person;
Person *pt2 = new Student; // base class pointer point to derived class
// Student *pt3 = new Person; // derived class pointer can not point to base class
Student *pt4 = new Student; delete pt1;
cout << "*********" << endl;
delete pt2;
cout << "*********" << endl;
//delete pt3;
//cout << "*********" << endl;
delete pt4;
cout << "*********" << endl; return 0;
}
运行结果:
- 不将基类析构函数声明为虚函数:
#include <iostream>
using namespace std; class Person{
public:
~Person(){ //declare destructor as a virtual function
cout << "Person::~Person()" << endl;
}
}; class Student : public Person{
public:
~Student(){ // virtual or not is OK
cout << "Student::~Student()" << endl;
}
}; int main(){
Person *pt1 = new Person;
Person *pt2 = new Student; // base class pointer point to derived class
// Student *pt3 = new Person; // derived class pointer can not point to base class
Student *pt4 = new Student; delete pt1;
cout << "*********" << endl;
delete pt2;
cout << "*********" << endl;
//delete pt3;
//cout << "*********" << endl;
delete pt4;
cout << "*********" << endl; return 0;
}
运行结果:
可以看出:
在用基类指针指向派生类时,
在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数。
在基类析构函数没有声明为virtual的时候,delete基类指针,只会调用基类的析构函数,而不会调用派生类的析构函数,这样会造成销毁对象的不完全。
分析:
Person *pt2 = new Student;
pt2的静态类型为Person,而动态类型为Student,
当析构函数为虚函数时,为动态绑定,delete pt2,会调用动态类型即派生类的析构函数,由于继承关系,也会调用基类的析构函数;
而当析构函数为非虚函数时,为静态绑定,delete pt2,会调用静态类型即基类的析构函数,而不会调用派生类的析构函数。
(以上纯属个人理解)
总结:
应该为多态基类声明虚析构器。一旦一个类包含虚函数,它就应该包含一个虚析构器,因为多态性,必定会有基类调用派生类。
如果一个类不用作基类或者不需具有多态性,便不应该为它声明虚析构器。
参考文章:
http://www.cnblogs.com/children/archive/2012/08/13/2636956.html
(C++)浅谈多态基类析构函数声明为虚函数的更多相关文章
- C++多态性中基类析构函数声明为虚函数
在用基类指针指向派生类时, 在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数. 在基类析构函数没有声明为virtual的时候,delete ...
- 条款7:为多态基类析构函数声明为virtual
基类指针指向子类对象. 子类对象必须位于堆.因此为了避免泄漏内存资源,当指针不使用时,delete掉每一个对象非常重要.但是如果基类的析构函数不声明为virtual.那么指向子类对象的指针delete ...
- why pure virtual function has definition 为什么可以在基类中实现纯虚函数
看了会音频,无意搜到一个frameworks/base/include/utils/Flattenable.h : virtual ~Flattenable() = 0; 所以查了下“纯虚函数定义实现 ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- c++ 子类,基类 中this指针 虚函数使用
笔记: 子类和基类 构造函数不显式时,的this指针相同..在QT中,如果父类基于QObject,那么构造子类时传入this指针,这样所有子类,父类,基类都是同一地址.delelater(),会del ...
- 抽象基类(ABC),纯虚函数
#ifndef _ACCTABC_H_ #define _ACCTABC_H_ //(* #include <iostream> #include <string> //*) ...
- 条款7:为多态基类声明virtual析构函数
C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的.其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用. # ...
- 读书笔记 effective c++ Item 7 在多态基类中将析构函数声明为虚析构函数
1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeepe ...
- 从零开始学C++之虚函数与多态(二):纯虚函数、抽象类、虚析构函数
一.纯虚函数 虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 在基类中不能给出有意义 ...
随机推荐
- 连接LilyPad之Linux平台的驱动
连接LilyPad之Linux平台的驱动 常用的Linux发行版都自带了FTDI驱动,因此在绝大多数Linux发行版中不需要用户进行额外的操作. 在LilyPad编程器被正确驱动后,就可以将LilyP ...
- FastReport.Net使用:[6]HTML标签使用
使用HTML标签的基础知识 1.FastReport所支持的HTML标签包括: ●粗体:<b>...</b> ●斜体:<i>...</i> ●下划线:& ...
- PHPStorm设置调试
先下载PHP扩展Xdebug https://xdebug.org, 可以复制自己的phpinfo粘贴到https://xdebug.org/wizard.php中, 会生成需要下载的版本, php. ...
- Opencv学习笔记2:图像模糊作用和方法
一.意义和作用: 图像的模糊处理就是将图片处理的更加模糊,如下图,左侧是原图,右侧是经过处理之后的图片. 从主观意愿上说,我们希望看到清晰的图像,而不是模糊的图像.所以很多时候我们听说还有一种专门进行 ...
- 【UOJ #204】【APIO 2016】Boat
http://uoj.ac/problem/204 肯定要离散化的,先离散化出\(O(n)\)个取值区间. 设\(f(i,j)\)表示第\(i\)所学校派出的划艇数量在\(j\)区间中. \(f(i, ...
- Tsinsen Palisection
建回文树. 正反建统计一种前缀和求出所有不相交的,用总数减去就是答案数. 在这里我们可以知道一个字符串中所有回文串的个数即为num数组之和(因为以一个节点为回文串结尾的字串都是唯一的) 也可以是cnt ...
- [BZOJ 3720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树
jzyzoj的p2016 先码着,强制在线的树分块或者树套树?关键是我树分块还在入门阶段树套树完全不会啊摔 http://blog.csdn.net/jiangyuze831/article/de ...
- java-银行卡基本信息查询
用于验证的请求接口: https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardNo= ...
- python开发_filecmp
filecmp模块用于比较文件及文件夹的内容,它是一个轻量级的工具,使用非常简单.python标准库还提供了difflib模块用于比较文件的内容.关于difflib模块,且听下回分解. filecmp ...
- April Fools Day Contest 2016 G. You're a Professional
G. You're a Professional 题目连接: http://www.codeforces.com/contest/656/problem/G Description A simple ...