1.对象
对象的建立存在多种可能方式。有些对象是局部变量,有些是全局变量,有些是类的成员,如此等等。初始化对象用到构造函数,在它们变得不可用时清理它们使用析构函数。
1.2 析构函数
构造函数完成对像的初始化,它建立起一种成员函数将在其中进行操作的环境。有时建立这样的环境涉及到申请某些资源——例如,一个文件,一个锁或者一个存储——这些资源在使用之后必须释放。这样,有些类里就需要有一个函数,并需要保证它将在每个对象被销毁之前得以调用,就像构造函数能够得到类似保证,在对象创建是必定被调用一样。按照这个习惯,这个函数被称为析构函数,它通常完成一些清理和释放资源的工作。当以个自动变量离开其作用域时,当一个位于自由存储的对象被删除是,还有在其他类似情况中,析构函数都将被隐式地调用。只有非常特殊的情况下,用户才需要去显示地调用析构函数。
析构函数的最简单的用途是为了释放构造函数请求的储存空间。考虑一个以某种类型Name为元素的简单的表Table。Table的构造函数必须为保存其元素分配储存,而到最后,当这种表被删除的时候,我们就必须保证这些储存能回收,以便将来再用。
我们做到这一点的方式就是提供一个与构造函数互补的特殊函数:
class Name{
const char* s;
// ....
};
class Table{
Name* p;
size_t sz;
public:
Table (size_t s=15) { p = new Name[sz = s]; } //构造函数
~Table() { delete[] p; }
}
析构函数的记法形式~Table() 采用求补的符号最为提示,以表明析构函数与构造函数Tabel()之间的关系。
1.3 默认构造函数
类似的,也可以认为大部分类型都有一个默认构造函数。默认构造函数就是调用时不必提供参数的构造函数。如果用户自己声明了一个默认构造函数,那么就会去使用它;否则,如果有必要,而且用户没声明其他的构造函数,编译器就设法去生成一个。
编译器生产的默认构造函数将隐式地位类类型的成员和他的基类调用有关的默认构造函数。例如,
strcut Tables{
int i;
int vi[10];
Table t1;
Table vt[10];
};
Tables tt;
这里的tt将被用一个生成出来的默认构造函数初始化,该构造函数为tt.t1以及tt.vt的每个成员调用Table(15)。另一方面,它不会去初始化tt.i和tt.vi,因为它们不是类类型的对象。对于类类型和内部类型区别对待是为了与C的兼容性,为了避免运行时的额外开销。
由于const和引用必须进行初始化,包含const或引用成员的类就不能进行默认构造,除非程序员显示地提供了默认构造函数。例如,
struct X{
const int a;
const int& r;
}
X x;//错误:无默认构造函数。