(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 解决方法 将这些接口定义为纯虚函数 在基类中不能给出有意义 ...
随机推荐
- Hat's Fibonacci hdu 1250
Problem Description A Fibonacci sequence is calculated by adding the previous two members the sequen ...
- 01-学前入门概念:.net与c#
.Net是由(.Net 平台和.Net FrameWork框架)这两部分组成. .Net FrameWork是由(CLR公共语言运行时和.Net 类库组成). .Net FrameWork框架是.Ne ...
- POJ 1741 树分治
题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...
- CSS 笔记——阴影、圆角、旋转、光标
7. 阴影.圆角.旋转.光标 (1)box-shadow 阴影 基本语法 text-shadow: h-shadow v-shadow blur color; box-shadow: h-shadow ...
- luoguP4366 [Code+#4]最短路 最短路
好久没写过博客了.... 本题还是挺有趣的(很水的最短路) 关键在于怎么优化这$n^2$条连边 通常,我们希望用一些边来替代一条边从而减小边集 那么,注意到异或操作可以拆分成按位运算,因此我们只需考虑 ...
- MySQL注射绕过技巧(三)
在测试一次注入的时候发现过滤了逗号 所以找到这个思路 第一次遇到的时候是看key哥挖洞 遇到后就想记录下来 正文 过滤了逗号 利用join来逐步查询 select*from(select 1)a ...
- bzoj 2809: [Apio2012]dispatching -- 可并堆
2809: [Apio2012]dispatching Time Limit: 10 Sec Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...
- 10.十进制转m进制
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 查看运行结果 题目描述 Description 将十进制数n转换成m进制数 m<=16 n<=1 ...
- 在windows上安装和启动Elasticseach、Kibana
写在前面的话:读书破万卷,编码如有神-------------------------------------------------------------------- 参考内容: <Ela ...
- asp.net mvc中DropDownList
asp.net mvc中DropDownList的使用. 下拉列表框 以分为两个部分组成:下拉列表和默认选项 DropDownList扩展方法的各个重载版本基本上都会传递到这个方法上: publi ...