C++基础--构造函数与析构函数
在C++中,有两种特殊的成员函数,即是构造函数和析构函数,下面分别予以介绍。
10.2.1 构造函数
变量应该被初始化,我们已经知道了简单变量的初始化、数组的初始化、结构和结构数组的初始化。对象也需要初始化,应该怎样初始化一个对象呢?
C++中定义了一种特殊的初始化函数,称之为构造函数。当对象被创建时,构造函数自动被调用。构造函数有一些独特的地方:函数的名字与类名相同,它也没有返回类型和返回值。
例如:
class Point {
public:
Point(int x = 0, int y = 0);
…
};
类Point的构造函数有两个参数,它们是赋给xVal、yVal的初始值,该构造函数的原型也为实参指定了缺省值0。
Point::Point(double x, double y)
{
xVal = x;
yVal = y;
}
我们也可以把该构造函数定义为内联函数的形式:
class Point {
Point (int x=0, int y=0) {xVal = x; yVal = y;} // 构造函数
…
};
如果不采用Point构造函数,我们将不得不调用SetPt函数初始化。可见,使用Point构造函数方便了编程,简化了程序代码。
现在,我们可以定义Point类对象并立即初始化它们:
Point pt1(10, 20); // xVal和yVal的初值分别为10和20
Point pt2; // xVal和yVal的初值均为0
构造函数也可以重载:
class Point {
int xVal, yVal;
public:
Point (int x, int y) { xVal = x; yVal = y; }
Point (float, float); //极坐标
Point (void) { xVal = yVal = 0; }
…
};
Point::Point (float len, float angle) //极坐标
{
xVal = (int) (len * cos(angle));
yVal = (int) (len * sin(angle));
}
创建Point对象时,可以使用这三种构造函数中的任一个。
Point pt1(10, 20); // 笛卡儿坐标
Point pt2(60.3, 3.14); // 极坐标
Point pt3; // 原点
用构造函数确保初始化
无论用什么方法使用类对象,都要求用户必须正确地初始化。在C + +中,可以通过一个叫做构造函数的特殊函数来保证每个对象正确地初始化。对象被创建时,构造函数被自动调用。所以,在我们使用一个对象之前,它的初始化就已经完成了。构造函数的特点是没有类型、没有返回值、名字与类名相同。下面是一个简单的类,它显式定义了构造函数:
class X
{
int i;
public:
X(); //构造函数
};
当用该类定义一个对象时:
void f()
{
X a;
//…
}
定义对象a与定义一个整型变量的方法并没有什么区别:为这个对象分配内存。但是,与定义一个整型变量也有不同的地方:当对象a创建时,会自动调用其构造函数。a的构造函数没有参数,实际上,构造函数也可以有参数。例如:Tree类的构造函数有一个整型参数,用以指定树的高度,创建Tree类对象的方法如下:
Tree t(12); // 12英尺高的树
Tree (int)的构造函数带一个整型参数,创建Tree对象时,必须指定该参数,用下面的语句创建Tree对象是错误的:
Tree t;
综上所述,构造函数是一个有着特殊名字,在对象创建时被自动调用的一种函数,它的功能就是完成类的初始化。
注意:
1、构造函数的作用是对对象本身做初始化工作,也就是给用户提供初始化类中成员变量的一种方式,在类对象有虚表的情况下,构造函数还对虚表进行初始化。
2、如果一个类中没有定义任何的构造函数,那么编译器只有在以下三种情况,才会提供默认的构造函数:
nA、如果类有虚拟成员函数或者虚拟继承父类(即有虚拟基类)时;
nB、如果类的基类有构造函数(可以是用户定义的构造函数,或编译器提供的默认构造函数);
n3、只要一个类定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C++就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参数的构造函数,则必须自己定义