ITEEDU

6.12 使用析构函数

析构函数是类的特殊成员函数。类的析构函数名是类名前面加上代字符(~)这种命名规则很直观,因为本章稍后将会介绍,代字运算符是按位取反符,从这个意义上,析构函数是构造函数的反函数。

类的析构函数在删除对象时调用,即程序执行离开初始化类对象的范围时。析构函数本身并不实际删除对象,而是进行系统放弃对象内存之前的清理工作,使内存可以复用于保存新对象。

析构函数不接受参数也不返回数值。类只可能有一个析构函数,不能进行析构函数重载。常见编程错误6.10

向析构函数传递参数、指定析构函数的返回值类型(即使指定void)、从析构函数返回数值或重载析构函数都是语法错误。

注意,前面介绍的类都没有提供析构函数。下面要介绍几个使用析构函数的例子。第8章将介绍析构函数适用于动态分配内存的对象类(例如数组和字符串)。第7章将介绍如何动态分配内存和释放内存。

软件工程视点6.21

稍后会介招,构造函数和析构函数在C++和面向对象编程中相当重要,不是这里的介绍所能说清楚的。

6.13 何时调用构造函数与析构函数

构造函数与析构函数是自动调用的。这些函数的调用顺序取决于执行过程进入和离开实例化对象范围的顺序。一般来说,析构函数的调用顺序与构造函数相反。但图6.9将介绍对象存储类可以改变析构函数的调用顺序。

全局范围中定义的对象的构造函数在文件中的任何其他函数(包括main)执行之前调用(但不同文件之间全局对象构造函数的执行顺序是不确定的)。当main终止或调用exit函数时(见第18章)调用相应的析构函数。

当程序执行到对象定义时,调用自动局部对象的构造函数。该对象的析构函数在对象离开范围时调用(即离开定义对象的块时)。自动对象的构造函数与析构函数在每次对象进人和离开范围时调用。

static局部对象的构造函数只在程序执行首次到达对象定义时调用一次,对应的析构函数在main终止或调用exit函数时调用。

图6.9的程序演示了CreateAndDestroy类型的对象在几种范围中调用构造函数与析构函数的顺序。程序在全局范围中定义first,其构造函数在程序开始执行时调用,其析构函数在程序终止时删除所有其他对象之后调用。

// Fig. 6,9: create,h
 // Definition of class CreateAndDestroy.
 // Member functions defined in create.cpp,
 #ifndef CREATE_H
 #define CREATE_H
 class CreateAndDestroy {
 public:
   CreateAndDestroy( int );  // constructor
   ~CreateAndDestroy();     // destructor
 private:
   int data;
 };
 #endif
 // Fig, 6.9: create.cpp
 // Member function definitions for class CreateAndDestroy
 #include < iostream.h>
 #include "create.h"
 CreateAndDestroy::CreateAndDestroy( int value )
 {
    data = value;
     cout << "Object "<< data <<"  constructor";
 }
 CreateAndDestroy::~CreateAndDestroyO
   { cout << "Object "<< data <<"  destructor "<< endl; }
 // Fig, 6.9: fig0609.cpp
 // Demonstrating the order in which constructors and
 // destructors are called.
 #include < iostream.h>
 #include "create.h"
 void create( void );  // prototype
 CreateAndDestroy first( 1 );  // global object
 int main()
{
   cout <<"  (global created before main)" << endl;
 CreateAndDestroy second( 2 );
   cout <<"  (local automatic in main)" << endl;
   static CreateAndDestroy third( 3 );  // local object
   cout <<"  (local static in main)" << endl;
   create();  // call function to create objects
   CreateAndDestroy fourth( 4 );      // local object
   cout <<"  (local automatic in main)" << endl;
   return 0;
 }
 // Function to create objects
 void create( void )
 {
   CreateAndDestroy fifth( 5 );
   cout <<"  (local automatic in create)" << endl;
   static CreateAndDestroy sixth( 6 );
   cout <<"  (local static in create)" << endl;
   CreateAndDestroy seventh( 7 );
   cout <<"  (local automatic in create)" << endl;
 }

输出结果:

Object 1 constructor (global creasted before main)

Object 2 constructor (local automatic in main)

Object 3 constructor (local static in main)

Object 5 constructor (local automatic in create)

Object 6 constructor (local static in create)

Object 7 constructor (local automatic in create)

Object 7 destructor

Object 5 destructor

Object 4 constructor (local automatic in main}

Object 4 destructor

Object 2 destructor

Object 6 destructor

Object 3 destructor

Object 1 destructor

图6.9调用构造函数与析构函数的顺序

函数main声明三个对象。对象second和fourth是局部自动对象,对象third是static局部对象。这些对象的构造函数在程序执行到对象定义时调用。对象fourth和second的析构函数在到达main结尾时依次调用。由于对象third是static局部对象,因此到程序结束时才退出,在程序终止时删除所有其他对象之后和调用first的析构函数之前调用对象third的析构函数。

函数create声明三个对象。对象fifth和seventh是局部自动对象,对象sixth是static局部对象。对象seventh和fifth的析构函数在到达删k结尾时依次调用。由于对象sixth是static局部对象,因此到程序结束时才退出。sixth的析构函数在程序终止时删除所有其他对象之后和调用third和first的析构函数之前调用。