学习笔记之深入浅出MFC 第8章 C++重要性质---构造函数与析构函数

C++的new云算子和C的malloc函数都是用于配置内存的,但是前者比之后者的优点是,new不但配置对象所需要的内存空间,同时会引发构造函数的执行。

所谓的构造函数(constructor),就是对象诞生后第一个执行(并且自动执行)的函数,它的函数名称必定要与类名称相同。

相对于构造函数,自然就有个解构(析构)函数,也就是在对象行将毁灭但未毁灭之前一刻,最后执行(并且自动执行)的函数,它的函数名称必定要与类名称相同,再在最前面加一个~符号。

一个有层次结构的类群租,当派生类的对象诞生之时,构造函数的执行是由最基类至最尾端派生类;当对象毁灭之前,解构函数的执行则是反其道而行。

对于构造函数和解构函数的执行的时间,针对不同的对象共可以分为四类:

1、对于全局对象(包括静态全局对象),程序一开始,其构造函数就先被执行(比程序进入点更早);程序即将结束前其解构函数被执行。  定义全局对象如下:  CFoo  foo;  //在任何函数范围之外做此操作

由于对象实现于任何“函数活动范围”之外,显然没有地方安置这样一个构造函数调用操作。这种静态全局对象的构造函数调用操作必须靠startup码帮忙。startup码是更早于程序进入点(main或winMain)执行起来的码,由C++编译器提供,被链接到你的程序中。startup码可能做些像函数库初始化、行程信息设立、I/O stream产生等等操作,以及对static对象的初始化操作(也就是调用其构造函数)。

当编译器编译你的程序,发现一个静态对象时,它会把这个对象加到一个连表中。更精确的说,编译器不只是加上这个静态对象,它还加上一个指针,指向对象之构造函数及其参数(如果有的话)。把控制权交给程序进入点(main或WinMain)之前,startup码会快速在该连表上移动,调用所有登记在案的构造函数并使用登记在案的参数,于是就初始化了你的静态对象。

2、对于局部对象,当对象诞生时,其构造函数被执行;当程序流程将离开该对象的存活范围(以至于对象将毁灭)时,其解构函数被执行。

void  MyFunc()

{

CFoo   foo;        //在堆栈(stack)中产生foo对象

}

这种局部情况C++在配置内存---来自堆栈(stack)或堆(heap)---之后立刻产生一个隐藏的(代码中看不出来的)构造函数调用。

3、对于静态(static)对象,当对象诞生时其构造函数被执行;当程序将结束时(此对象因而将遭致毁灭)其解构函数才被执行,但比全局对象的解构函数早一步执行。

void  MyFunc()

{

static  CFoo   foo;      //在函数范围之内的一个静态对象

}

这种局部静态变量相当于C语言中的静态局部变量,只会有一个实例(instance)产生,而且在固定的内存上(既不是stack也不是heap)。它的构造函数在控制权第一次转移到其声明处(也就是MyFunc第一次被调用)时被调用。

4、对于以new方式产生出来的局部对象,当对象诞生时其构造函数被执行。解构函数则在对象被delete时执行。

void  MyFunc()

{

CFoo*  pFoo  =  new  CFoo();     //在堆(heap)中产生对象

}

C++在配置内存之后立刻产生一个隐藏(程序代码看不出来的)构造函数调用。

使用GDI+库显示gif动态图片,该类接口如下: 可以看出,该ImageEx完全继承了基类的接口函数。 说明: 如果打开非多帧图片,该类几乎完全等价于基类,比如你可以把该类的对象代入Graphics类系列的成员函数中; 如果打开的是多帧的图片,你只要打开图片后不调用InitAnimation函数(它会创建线程),则上述做法依然可以; 但如果调用InitAnimation函数后(单帧图像没关系,因为不会创建线程),则不可以了, 所有的基类继承过来的接口成员函数和配合gdi+库其他类的函数调用都是不可以的,因为没有作线程同步, 你只能调用下面位数不多的几个public成员函数,调用Destroy成员函数后,则就可以了,因为它会关闭线程。 其实你会发现下面的public成员函数操作的成员变量都是新增的成员变量,没涉及到线程同步问题。 class ImageEx : public Image { public: //以长度为nSize的内存pBuff中的内容构造图像 ImageEx(const void* pBuff, size_t nSize, BOOL useEmbeddedColorManagement = FALSE); //以类型为sResourceType,名称为sResource的资源构造图像 ImageEx(LPCTSTR sResourceType, LPCTSTR sResource, BOOL useEmbeddedColorManagement = FALSE); //以文件构造图像 ImageEx(LPCTSTR filename, BOOL useEmbeddedColorManagement = FALSE); //调用Destroy成员函数 ~ImageEx(); public: //如果已经构造的对象是动画,则创建动画线程,并返回true, //如果为静态图像或已经创建过动画线程,则也返回false // 图像将绘制在m_hWnd客户区的rect区域,会拉伸,支持镜像 bool InitAnimation(HWND hWnd, RECT rect); //判断是否为动画 bool IsAnimatedGIF() { return m_nFrameCount > 1; } //设置动画暂停与否 void SetPause(bool bPause); //判断动画是否处于暂停状态 bool IsPaused() { return m_bPause; } //关闭动画,事实上基类Image中还有的两个成员变量没有关闭,因为析构函数会调用基类析构函数进行关闭的 void Destroy(); //另外的非public的东西省略.. }; 用法: MFC对话框程序在下面添加: BOOL CTestDlgDlg::OnInitDialog() { CDialog::OnInitDialog(); //其它的初始化代码 // GDI+ //m_image为ImageEx指针类型成员变量,"GIF"为资源类型,"HEARTS"为资源名称 m_image = new ImageEx( _T("GIF"), _T("HEARTS") ); RECT rc; GetClientRect(&rc); m_image->InitAnimation(this->m_hWnd, rc);//创建gif播放线程 return TRUE; // return TRUE unless you set the focus to a control } CTestDlgDlg::~CTestDlgDlg() { // GDI+ delete m_image; } 其中的m_image = new ImageEx( _T("GIF"), _T("HEARTS") );你可以换成ImageEx类的另外两个构造函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值