必备技能8.4:构造函数和析构函数
在前面的例子中,我们可以看到Vechile类的对象的实例变量必须通过如下的代码段来手工地进行初始化:
minivan.passengers = 7;
minivan.fuelcap = 16;
minivan.mpg = 21;
在专业的C++代码中,这样的方式是不会被用到的。因为这样除了容易出错之外还可能造成忘记了给某个成员变量进行初始化。其实有一个更简单的方式来完成这样的事情:构造函数。
构造函数在对象被创建的时候就对其进行初始化。它的名字和类的名字是一样的,在语法上和函数很相似。然而,构造函数没有明确的返回值类型。构造函数的通行形式如下:
class-name()
{
//constructor code
}
通常情况下,我们使用构造函数来给实例变量进行初始化,或者是在其中进行一些别的工作来创建一个完整的对象。
和构造函数相对应的就是析构函数。在大多数的情况下,当一个对象被销毁的时候,我们需要做一些或者一些列的善后工作。局部对象在进入相应的代码段的时候被创建,并在离开其所在代码段的时候被销毁。全局的对象会在程序结束的时候被销毁。这里就有很多因素导致我们需要析构函数。例如,在销毁对象的时候,需要释放之前为其分配的内存空间;或者关闭之前有它打开的文件。在C++中正是由析构函数来做这些事情的。析构函数的名字和构造函数的名字是一样的,但是需要在前面加上~。和构造函数一样,析构函数也是没有返回类型的。
下面就是一个使用了构造函数和析构函数的简单的例子:
//一个简单的演示构造函数和析构函数的程序
#include <iostream>
using namespace std;
class MyClass
{
public:
int x;
//声明构造函数和析构函数
MyClass();
~MyClass();
};
//实现构造函数
MyClass::MyClass()
{
x = 10;
}
//实现析构函数
MyClass::~MyClass()
{
cout << "Destructing ... \n";
}
int main()
{
MyClass ob1;
MyClass ob2;
cout << ob1.x << " " << ob2.x << "\n";
return 0;
}
上面程序的输出如下:
10 10
Destructing ...
Destructing ...
在上面的这个例子中,MyClass类的构造函数就是:
//实现构造函数
MyClass::MyClass()
{
x = 10;
}
注意上面的构造函数是被声明为共有的。这是因为MyClass类的构造函数是在该类之外被调用的。在构造函数中给MyClass类的实例变量x赋值为10。这个构造函数在MyClass类的对象被创建的时候被调用。例如,在下面的代码行中:
MyClass ob1;
构造函数MyClass()就会被针对对象ob1而调用,也就是给ob1的实例变量x赋值为10。同样对ob2来说也是这样的。在ob2被创建后,其x的值也是10。
MyClass类的析构函数如下:
//实现析构函数
MyClass::~MyClass()
{
cout << "Destructing ... \n";
}
这个析构函数只是简单的显示了一条信息。但是在真实的程序中,析构函数会被用来释放有该对象使用的一个或者多个资源的(例如,文件句柄或者内存空间)。
练习:
1. 什么是构造函数,它在什么时候会被执行?
2. 构造函数是否有返回值类型?
3. 析构函数什么时候会被调用?