C++学习笔记25,永远将析构函数声明为virtual

要永远记得将析构函数声明为virtual----><<effective c++>>

或许你觉得这句话不一定对,但无需质疑的是这句话是很有用的.

查看下面的例子:

#include <iostream>
#include <string>
using namespace std;
class B{
public:
	~B(){
		cout<<"base is destroyed!"<<endl;
	}
};
class D:public B{
public:
	~D(){
		cout<<"dirved is destroyed!"<<endl;
	}

};

int main(){
	{
	D d;
	}
}

这个是一个很简单的例子,输出是肯定的.

但是,再看下面的测试!

#include <iostream>
#include <string>
using namespace std;
class B{
public:
	~B(){
		cout<<"base is destroyed!"<<endl;
	}
};
class D:public B{
public:
	~D(){
		cout<<"dirved is destroyed!"<<endl;
	}

};

int main(){
	{
	B *b=new D();
	delete b;
	}
}

因此可以看到,当用一个基类的指针指向一个派生类的对象,直接删除该指针时,析构函数调用链将会遭到破坏.

#include <iostream>
#include <string>
using namespace std;
class B{
public:
	virtual ~B(){
		cout<<"base is destroyed!"<<endl;
	}
};
class D:public B{
public:
	virtual ~D(){
		cout<<"dirved is destroyed!"<<endl;
	}

};

int main(){
	{
	B *b=new D();
	delete b;
	}
}

因此应该记得将析构函数声明为virtual,这样就永远不用担心析构函数调用链遭到破坏!

C++学习笔记25,永远将析构函数声明为virtual

时间: 2024-08-03 07:38:21

C++学习笔记25,永远将析构函数声明为virtual的相关文章

条款7:为多态基类析构函数声明为virtual

基类指针指向子类对象. 子类对象必须位于堆.因此为了避免泄漏内存资源,当指针不使用时,delete掉每一个对象非常重要.但是如果基类的析构函数不声明为virtual.那么指向子类对象的指针delete时,析构掉的成分都是基类的,而子类的成分没有被识别出来,而未被析构掉.这样就造成资源浪费.给基类析构函数声明为virtual,那么delete对象时,就会是你希望的那样,它会销毁整个对象,包括所有继承类(drived class)的成分.析构时调用顺序:先调用最深层次的派生类的析构函数,依次向上调用

[原创]java WEB学习笔记25:MVC案例完整实践(part 6)---新增操作的设计与实现

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

PHP学习笔记十九【析构函数】

<?php class Person{ public $name; public $age; public function __construct($iname,$iage) { $this->name=$iname; $this->age=$iage; } //定义一个析构函数 两个下划线 ,析构函数在对象被释放的时候会自动调用 //最先被创建最后被销毁,因为是放入栈中,栈是先进后出 //析构函数调用的时机 //1.当程序(进程结束)退出时 //2.当一个对象成为垃圾对象(没有任何变

c++学习笔记之基础---类内声明函数后在类外定义的一种方法

在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类内声明函数后在类外定义的一种方法!如果不加"类名::"的话,编译系统就不会知道你的函数属于哪个类;另外,这样定义函数一定要在类中声明之后,说明它是类的成员函数才可以!在类内声明的时候就不需要::了,直接 返回值类型 函数名(参数表) 就可以了!

【学习笔记】JavaScript编码规范-声明提升

变量声明应该在作用域的顶端,但是赋值没有. function example(){ var declaredButAssigned; //如下输出 declaredButNotAssigned 未定义 console.log(declaredButNotAssigned) declaredButNotAssigned = true } 匿名表达式能提升他们的变量名,但不能提升函数赋值. function example(){ console.log(anonymous); //未定义 anony

10-黑马程序员------C 语言学习笔记--- C语言函数的声明和原型

黑马程序员------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 三 函数的声明和原型 01 在函数调用之前,应该对所调用函数进行声明,指出该函数的返回值类型及形参的个数和类型. 函数声明的一般格式: 函数返回值类型 函数名(形参类型1 形参名1,………………); *函数声明的位置,一种是在主

c++学习笔记之基础---类内声明线程函数的调用

近日需要将线程池封装成C++类,类名为Threadpool.在类的成员函数exec_task中调用pthread_create去启动线程执行例程thread_rounter.编译之后报错如下: spfs_threadpool.cpp: In member function ‘int Threadpool::exec_task(task*)’: spfs_threadpool.cpp:174: error: argument of type ‘void* (Threadpool::)(void*)

vue学习笔记之初识vue——实例方法声明

如果需要在点击鼠标时,执行一个复杂的操作,那么采用单一的表达式 作为v-on指令值就不够了 -- 我们需要将复杂的操作封装为Vue实例的 一个方法,然后将v-on指令的值设置为这个方法. 使用methods配置项来声明Vue实例的方法.当Vue.js创建一个Vue实例时, 会将methods配置项中声明的方法,挂接到Vue实例对象上: 实例方法可以直接通过实例对象调用,例如,对于上图中的vm实例: vm.handler(); //正确 实例方法另一个常见的用途,是将方法名声明为v-on指令的值,

Java学习笔记25

Collection和Map接口是集合框架的根接口,List为Collection接口的子接口,List集合代表一个元素有序.可重复的集 合,集合中每个元素都有其对应的顺序索引.List集合允许使用重复元素,可以通过索引来访问指定位置的集合元 素. List作为 Collection接口的子接口,可以使用 Collection接口里的全部方法.List是有序结合,因此List集合里增加了一 个根据索引来操作集合元素的方法. boolean addAll(int index, Collection