对于c++这门语言存在众多的构造函数,如:默认构造函数,拷贝构造函数,转换构造函数。真是相当的多,也相当的复杂。这里就对这三种构造函数做个简短的说明:
1.默认构造函数:
即创建对象时,编译器自动调用的函数,主要用来生成相应的对象及对private属性进行必要的初始化。就如之前文章介绍过的一样,对于对象数据成员和const数据成员,我们一定要用相应的初始化列表器来做相应的初始化(此时,初始化列表器在构造函数体之前执行,对于const数据成员,也就是说在初始化之后,这个数据成员才是真正的const常量数据。而之前一直属于未定义状态。)。
2.拷贝构造函数:
编译器会默认为每一个对象提供一个默认拷贝构造函数。这个构造函数的用途就是用已有对象来初始化新建对象。创建时编译器自动调用。例: string s1(s2);//s2也是string对象,用s2来初始s1。此时系统就会自动调用相应的拷贝函数来执行相应的操作。还有一种是声明对象同时初始化。例:string s3 = s1; //此时也调用相应的拷贝构造函数。而不是重载的赋值运算符。那拷贝函数内部是如何做到的呢?机制就是数据成员逐一赋值来完成的。(默认拷贝函数的缺点在于:如果对象内部通过new来申请了内存空间,那么通过这种方式进行逐一的赋值,会产生两个对象的数据成员指针指向同一块内存,如果其中的一个对象调用了delete删除相应的内存,那么另一个对象数据成员指针就指向了一个空的内存(此时指针叫做空悬指针),会产生严重的运行时错误。所以这里对于创建类对象内部new内存空间的,一定要重载相应的拷贝构造函数来避免产生空指针错误。
3.转换构造函数:
编译器会默认把单参数构造函数来当做相应的转换构造函数来执行隐式类型转换。打个比方:void print(const Array &);//函数原型,指明这个函数接受一个Array类型的对象引用,并打印此对象中的数组元素。此时Array类的构造函数为 Array(int); //带一个参数的产生数组的构造函数(即对象内部维护了一个int类型的数组)。而打印函数print()明确指明了要接受一个Array类型的引用,而此时我们在print(3)函数中放入相应的int类型的整数3。此时照理说,肯定编译的时候要出错才是的,而此时编译器在背后隐式的调用了转换构造函数(即带一个参数的构造函数)。把int整数3默认转换成一个生成3个数组的Array临时对象。自动完成了这背后的转变。缺点:对于编译器对于基本类型默认转换成相应的对象,可能会引起程序的逻辑错误。因此,我们必需要加上相应限制符来阻止编译器的这一隐式类型转换(即:当编译这样类未定义的print(3)函数时,产生一个错误.就像我们刚开头的时候设想的一样,默认提示错误信息,而不是自动完成相应的转换)。讲了半天,那我们应该怎样用限制符呢?其实很简单,只要在相应的头文件中在构造函数的开头加上expcilit关键字即可,而相应的源文件*.cpp不用做任何的修改。当编译器遇到explicit关键字时,就不会做隐式类型转换了。