引用类的析构函数和终结器
来源:互联网 发布:汤圆的一个软件 编辑:程序博客网 时间:2024/05/16 19:17
摘要:《Visual C++ 2008入门经典》第9章类继承和虚函数,本章我们将研究面向对象编程的核心主题-- 类继承。本小节为大家介绍引用类的析构函数和终结器。
我们可以用为本地C++类定义析构函数时所用的相同方式,为引用类定义析构函数。当某个引用类的句柄离开其作用域时,或者当该类的对象是另一个正在被销毁的对象的组成部分时,类的析构函数将被调用。我们也可以对引用类的句柄应用delete运算符,这样也会调用析构函数。为本地C++类实现析构函数的首要原因是要处理在堆上分配的数据成员,但该理由显然不适用于引用类,因此在引用类中很少需要定义析构函数。当类对象要使用不被垃圾回收器管理的其他资源时,我们可能才需要定义析构函数。我们也可以使用另一种名为终结器(finalizer)的类成员来清除这样的资源。
终结器是一种特殊的引用类函数成员,是在销毁对象的时候由垃圾回收器自动调用的。注意,如果析构函数被显式调用,或者因为对某个对象应用delete运算符而被调用,那么垃圾回收器将不会为该对象调用终结器。在派生类中,调用终结器的顺序与调用析构函数的顺序相同,因此最基本的类的终结器被首先调用,然后是类层次结构中下一个类的终结器被调用,最后被调用的是最后派生的那个类的终结器。
下面是定义类终结器的方法:
- public ref class MyClass
- {
- // Finalizer definition
- !MyClass()
- {
- // Code to clean-up when an object is destroyed...
- }
- // Rest of the class definition...
- };
在类中定义终结器的方法与定义析构函数的类似,但需要用!代替为析构函数使用的类名前面的~符号。与析构函数一样,我们决不能为终结器提供返回类型,而终结器的访问说明符也将被忽略。通过下面这个小示例,我们可以了解一下析构函数和终结器的工作情况。
试一试:终结器和析构函数
该示例说明了应用程序中调用析构函数和终结器的时间:
- // Ex9_20.cpp : main project file.
- // Finalizers and destructors
- #include "stdafx.h"
- using namespace System;
- ref class MyClass
- {
- public:
- // Constructor
- MyClass(int n) : value(n){}
- // Destructor
- ~MyClass()
- {
- Console::WriteLine("MyClass object({0}) destructor called.", value);
- }
- // Finalizer
- !MyClass()
- {
- Console::WriteLine("MyClass object({0}) finalizer called.", value);
- }
- private:
- int value;
- };
- int main(array<System::String ^> ^args)
- {
- MyClass^ obj1 = gcnew MyClass(1);
- MyClass^ obj2 = gcnew MyClass(2);
- MyClass^ obj3 = gcnew MyClass(3);
- delete obj1;
- obj2->~MyClass();
- Console::WriteLine(L"End Program");
- return 0;
- }
该示例的输出如下:
- MyClass object(1) destructor called.
- MyClass object(2) destructor called.
- End Program
- MyClass object(3) finalizer called.
示例说明
MyClass类包含一个构造函数、一个析构函数和一个终结器。析构函数和终结器仅仅将输出写到命令行上,以便使我们知道它们被调用的时间。我们还能够辨别出是哪个对象调用了终结器或析构函数,因为这两个函数还将输出value字段的值。
在main()函数中,我们创建了3个为了区别而封装了数值1、2和3的MyClass类型的对象。然后,我们先是对obj1应用delete运算符,之后又显式调用obj2的析构函数。这些显式动作导致的对对象析构函数的调用生成了前两行输出。
下一行输出是main()中return语句之前的那条语句产生的,因此obj3的终结器生成的最后一行输出发生在main()结束之后。输出表明,当我们删除某个对象或显式调用某个对象的析构函数时,该对象的析构函数将被执行,这些操作同时禁止了该对象的终结器的执行。obj3引用的对象是程序终止时由垃圾回收器销毁的,因此调用了终结器来清除任何不受管理的资源。
因此,如果某个类既有终结器,又有析构函数,则销毁对象时只能调用其中之一。如果我们以编程方式销毁对象,则析构函数被调用;如果对象因离开作用域而自然消亡,则终结器被调用。由此还可以得出下面的结论:如果我们依赖终结器来完成销毁对象之后的清理工作,则不应该显式删除对象。
如果我们使main()中销毁obj1和obj2的语句以注释形式存在,那么将看到程序结束时垃圾回收器调用了所有这3个对象的终结器。另一方面,如果我们使MyClass类的终结器以注释形式存在,那么将发现垃圾回收器没有调用obj3的析构函数,因此没有任何清理动作发生。我们的结论如下:如果无论对象以怎样的方式终止,都希望确保对象使用的不受管理的资源能够得到清理,则应该在类中既实现析构函数,又实现终结器。
回书目 上一节 下一节
- 引用类的析构函数和终结器
- C#析构函数(destructor)和终结器(Finalizer)
- C# 析构函数(destructor)和终结器(Finalizer)
- C#析构函数(destructor)和终结器(Finalizer)
- C# 析构函数(Destructor)和终结器(Finalizer)——托管资源的释放
- cpp之间函数引用和类引用的方法
- Linux下进程的“终结者”和Linux C函数
- 析构函数和虚函数的用法和作用指针与引用的区别
- qt中出现对构造函数和析构函数未定义的引用
- 函数指针和函数引用的区别
- 函数指针和函数引用的区别
- 函数指针和函数引用的使用
- PHP类中成员变量和函数的引用
- 类成员函数返回对象和返回引用的区别
- 终结JBuilder2005的智能类型函数提示
- 终结JBuilder2005的智能类型函数提示
- 找不到引用协定“××”的默认终结点元素
- 引用和非引用不能区分函数的重载
- LAMP的容量规划之道 -- flickr的运维分享
- 手机日常维护
- 可以上传、下载文件的SSH客户端软件--SecureCRT绿色版
- Linux下安装OpenSSL
- 十六进制转化为带符号位的十进制
- 引用类的析构函数和终结器
- JRE system library错误。
- 转:Linux系统管理学习路线图
- .net 网站优化
- [GT学习笔记一]快速入门
- .net 删除文件夹及里面的文件
- Port Windows IPC apps to Linux, Part 2: Semaphores and events
- 在WIN7上安装VS2003(FrontPage扩展的问题)
- 杂乱之android的AlertDialog应用