析构函数的奥秘

请看如下一段代码:

class A {
public:
A () { pValue = new int[100]; printf("Constructor of A\n"); }
~A () { delete [] pValue; printf("Deconstructor of A\n"); }
private:
int * pValue;
};

class B {
public:
~B () { printf("Deconstructor of B\n"); }
};

class C : public B {
public:
~C () { printf("Deconstructor of C\n"); }
private:
A a;
};
int main(int argc, char* argv[])
{
C c;
return 0;
}

类C从类B中继承出来,类C中聚合了一个类A的对象,类C的析构函数并未调用类A的析构函数,请问:这段代码执行后,会调用类A的析构函数释放内存吗?经测试,执行结果如下:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

由此可以看出,C的析构函数确实调用了类A的析构函数,该调用是由编译器隐含加入的,随后还调用了基类B的析构函数,但是请注意,编译器只会为基类和聚合类添加对析构函数的调用,如果C中的成员为指向类A的指针,则编译器不会加入对类A的析构函数的调用。

那么,如果我们把main函数改变一下:

int main(int argc, char* argv[])
{
B * b = new C;
delete b;
return 0;
}

请问:这段代码会发生内存泄漏吗?执行结果如下:

Constructor of A
Deconstructor of B

发生了什么?调用了A的构成函数分配了内存,却只调用了B的析构函数,C和A的析构函数都没有调用,内存没有释放,为什么?

有人也许已经看出了问题所在,B和C的析构函数都应该是虚函数,否则,由于b的类型为指向类B的指针,delete b只会调用B的析构函数。当B和C的析构函数都是虚函数时,编译器会根据b指向的对象实际上是C的对象,而去调用C的析构函数。请对代码作如下改变:

class B {
public:
virtual ~B () { printf("Deconstructor of B\n"); }
};
class C : public B {
public:
virtual ~C () { printf("Deconstructor of C\n"); }
private:
A a;
};

再次运行,结果正确:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

时间: 2024-11-19 00:37:58

析构函数的奥秘的相关文章

C++函数专题

局部变量的作用域-多线程和函数里的静态变量 关于C++类成员函数的重载.覆盖.隐藏与virtual关键字 在C++中使用Lambda函数提高代码性能 关于拷贝构造函数和赋值运算符 析构函数的奥秘 C++中强制转换函数总结 C++中的延时函数 C++中的类静态成员和静态成员函数 c与c++中的time相关函数 C++空类的默认成员函数总结 C++指针探讨(四)函数对象 C++指针探讨(三)成员函数指针 C++指针探讨(二)函数指针 C++回调函数用法 vcl库函数 在Delphi与C++之间实现函

C++类成员构造函数和析构函数顺序示例详细讲解_C 语言

对象并不是突然建立起来的,创建对象必须时必须同时创建父类以及包含于其中的对象.C++遵循如下的创建顺序: (1)如果某个类具体基类,执行基类的默认构造函数. (2)类的非静态数据成员,按照声明的顺序创建. (3)执行该类的构造函数. 即构造类时,会先构造其父类,然后创建类成员,最后调用本身的构造函数. 下面看一个例子吧 复制代码 代码如下: class c{public:    c(){ printf("c\n"); }protected:private:}; class b {pub

理解finalize()-析构函数替代者

函数 理解finalize()-析构函数替代者   在许多方面,Java 类似于 C++.Java 的语法非常类似于 C++,Java 有类.方法和数据成员:Java 的类有构造函数: Java 有异常处理.       但是,如果你使用过 C++ 会发现 Java 也丢掉一些可能是你熟悉的特性.这些特性之一就是析构函数.取代使用析构函数,Java 支持finalize() 方法.       在本文中,我们将描述 finalize() 与 C++ 析构函数的区别.另外,我们将创建一个简单的 A

Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(一)

原文 http://www.cnblogs.com/mayswind/archive/2013/03/17/2962205.html   [题外话] 这是2010年参加比赛时候做的研究,当时为了实现对Word.Excel.PowerPoint文件文字内容的抽取研究了很久,由于Java有 POI库,可以轻松的抽取各种Office文档,而.NET虽然有移植的NPOI,但是只实现了最核心的Excel文件的读写,所以之后查了很多资料才实 现了Word和PowerPoint文件文字的抽取.之后忙于各种事情

ASP 类成员变量、成员函数、构造析构函数

class CFoo    dim publicParam '用 dim 申明公有成员变量    private privateParam '用 private 申明私有成员变量    'publicParam = "公有" '不能在 class 标记以内.类函数以外为成员变量赋值    'const MAX_LEN = 5 '不能在 class 标记以内.类函数以外使用 const        '该函数为构造函数,在使用 set new 创建对象时,自动执行    private

网站配色奥秘大公开

配色 网站配色奥秘大公开曾经费尽心思想替网站设计一套令人眼睛为之一亮的色彩组合吗?或者你一直不解为何银行.公司行号或金融机构的网站总是使用蓝色系?那么你来对地方了.虽然大部分的网站开发人员都很清楚网络所使用的色盘和计算色彩的 16 进位系统,但对色彩学和有效色彩组合背后所隐含的原理依然懵懵懂懂. 几世纪以来,颜色本身就是一个难解的谜题.举例子来说,苏格拉底就曾经假设说「火」之源起,乃是因眼睛结合了对象本身的「白」(whiteness)所产生的颜色.之后,牛顿更探索光与色彩之间的关系:其后历经许多

中国奥秘的艰难成长之路

我是在高一时买电脑的.但那时并没有人教导我,自己完全是个电脑文肓.对于安装系统,安装驱程这些根本就是不知所云!我记得当时是很流行罗马帝国的游戏.也是那个时候开始接触到互联网.那时我对互联网是充满着幢景向往的,也没有想到自己去做一个网站.只是很佩服那些能做出网站的人.而自己却从来没有想过去拥有自己的网站.那时主要是觉得要很高技术才能做到. 三年高中买回的电脑就是学打五笔,及打罗马帝国.直到读大学,由于我选读的是计算机网络的,这才是我真正接解互联网.刚开始是学习网页基本编码HTML,后来就学习网页常

C#中构造函数和析构函数的用法

函数 摘 要:构造函数与析构函数是一个类中看似较为简单的两类函数,但在实际运用过程中总会出现一些意想不到的运行错误.本文将较系统的介绍构造函数与析构函数的原理及在C#中的运用,以及在使用过程中需要注意的若干事项. 关键字:构造函数:析构函数:垃圾回收器:非托管资源:托管资源一.构造函数与析构函数的原理 作为比C更先进的语言,C#提供了更好的机制来增强程序的安全性.C#编译器具有严格的类型安全检查功能,它几乎能找出程序中所有的语法问题,这的确帮了程序员的大忙.但是程序通过了编译检查并不表示错误已经

Windows各系列启动速度差异的奥秘

Windows各系列启动速度差异的奥秘 作者:计算机基础教程网    来源:www.itwen.com    更新时间:2006-02-09 [ 收藏此页到: 天天 | 和讯 | 博采 | ViVi | 狐摘 | 我摘 ]   不知道大家有没有留意,最近两年Windows的版本,启动进入图形界面的所需时间有加长的趋势,这纯粹是系统没优化好吗?其实Windows从诞生的那天开始,其核心和任务的侧重点经历了三次变化,加上它们对储存设备利用的不同,导致了Windows各个系列启动速度的差异.我们就来看