各种构造函数的区别
构造函数(包括拷贝构造函数)的基本功能:分配空间,初始化数据.
构造函数名和类名一样
一.默认构造函数.
与用户自定义构造函数相比,默认构造函数有功能缺陷:只能分配空间,完成不了初始化数据的任务(类的数据成员都是基本类型数据类型时的默认拷贝构造函数是个例外).
1.一般的默认构造函数
若用户没有定义任何构造函数(包括拷贝构造函数),则编译器自动添加默认构造函数(不带任何参数),但该函数不作任何实际工作.即它不能完成对类的数据成员的初始化工作,若用户在用其它方式初始化这些数据成员之前对它们进行访问,就会出错.因此,在任何情况下,用户都应该自定义构造函数,而不使用编译器提供的默认构造函数.
2.默认拷贝构造函数
若用户没有定义拷贝构造函数,则编译器自动添加默认拷贝构造函数(带一个该类类型的参数),称为浅拷贝.它只能完成基本类型数据类型(如int型变量)的拷贝,若类中有动态数组等数据类型,浅拷贝就会出问题.即是说,浅拷贝有潜在危险(当类的数据成员都是基本类型数据类型时,它是安全的).因此,在任何情况下,用户自定义拷贝构造函数是可取的.
二.用户自定义的构造函数(可以重载).
用户自定义的构造函数需要完成两个功能:分配空间,初始化数据.
1.一般的用户自定义构造函数
(1).无参数的自定义构造函数
该函数允许用户如此定义类的对象
ClassName c; //该定义类对象的形式很重要,
ClassName* C=new ClassName[2]; /*
ClassName D[2]; /*该段代码调用的就是无参数的 自定义构造函数.*/
(2).一般的自定义构造函数(可以允许部分形参有对应默认参数)
带有若干参数,调用时显式的写明实参.
ClassName c(...);
ClassName C[2]={(...),(...)};
(3).所有形参都有对应默认参数自定义构造函数
相当于复合了1与2的功能,是常用的且很方便的一种方法.
ClassName* C=new ClassName[2];
ClassName D[2]={(...),(...)};
2.用户自定义的拷贝构造函数
为了安全,是很有必要定义的.
//1.构造函数不能有返回值
//2.缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空
// 3.创建一个对象时,系统自动调用构造函数。但如果是用类的一个对象去初始化该类的另一个对象,则调用拷贝构造函数。
三、析构函数
//析构函数没有参数,也没有返回值。不能重载,也就是说,一个类中只可能定义一个析构函数。
//如果一个类中没有定义析构函数,系统也会自动生成一个默认的析构函数,为空函数,什么都不做。
//调用条件:1.在函数体内定义的对象,当函数执行结束时,该对象所在类的析构函数会被自动调用;
//
四、拷贝构造函数
//拷贝构造函数实际上也是构造函数,具有一般构造函数的所有特性,其名字也与所属类名相同。
//拷贝构造函数中只有一个参数,这个参数是对某个同类对象的引用。
//在三种情况下被调用:1.用类的一个对象去初始化该类的另一个对象时; //见程序员面试宝典-P.111例5:调用析构函数,调用拷贝构造函数
如:
int x,y;
public:
string(int a, int b) // 构造函数
{ x=a;y=b;}
string(const string & other) // 拷贝构造函数 , 定义other是引用变量,“引用const string型”的引用变量。
{ x=2*other.x;y=2*other.y;}
};
main()
{
string p1(30,40); //定义对象p1,调用了普通的构造函数
string p2(p1); //这里会调用拷贝构造函数,&other,把p1引用过来(或理解为指向p1),用p1初始化p2
cout<<p1.x<<p1.y<<endl;
cout<<p2.x<<p2.y<<endl;
}
//
//
//