拷贝构造函数
拷贝构造函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本
类的对象的引用。其作用是使用一个已经存在的对象(由拷贝构造函数的参数指定的对
象),去初始化一个新的同类的对象。
用户可以根据自己实际问题的需要定义特定的拷贝构造函数,以实现同类对象之间
数据成员的传递。如果用户没有声明类的拷贝构造函数,系统就会自动生成一个缺省函
数,这个缺省拷贝函数的功能是把初始值对象的每个数据成员的值都复制到新建立的对
象中。因此,也可以说是完成了同类对象的克隆(Clone),这样得到的对象和源对象具
有完全相同的数据成员,即完全相同的属性。
定义一个拷贝构造函数的一般形式为:
class 类名
{
public:
类名<形参表>; // 构造函数
类名<类名&对象名>; // 拷贝构造函数
…
};
类名::类名(类名&对象名) // 拷贝构造函数的实现
{
函数体
}
例8-2-1 拷贝构造函数举例。
对于直角坐标系中的圆,可以通过给出它的半径R,圆心的坐标值X 和Y 来确定。
定义一个圆的类Circle:
class Circle
{
public:
Circle(int rr=10,int xx=0,int yy=0)
{
R=rr;X=xx;Y=yy;
} // 构造函数
Circle(Circle &c); // 拷贝构造函数
int GetR() {return R;}
int GetX() {return X;}
int GetY() {return Y;}
private:
int R,X,Y;
int i=0;
};
类中定义了内联构造函数和拷贝构造函数。拷贝构造函数的实现如下:
Circle::Circle(Circle &c)
{
R = c.R;
X = c.X;
Y = c.Y;
i++;
cout << "拷贝构造函数被调用" << i << "次" << endl;
}
普通的构造函数是在对象创建时调用,而拷贝构造函数在以下三种情况下都会被调
用:
⑴当类的一个对象去初始化该类的另一个对象时。例如:
int main()
{
Circle A(10,5,5);
Circle B(A); // 用对象A 初始化对象B,拷贝构造函数被调用
cout << B.GetR() << endl;
return 0;
}
⑵如果函数的形参是类的对象,形参和实参结合时,调用拷贝构造函数。例如:
void fun1(Circle c)
{
cout << "R=" << c.GetR() << endl;
}
int main()
{
Circle A(10,5,5);
fun1(A) // 函数的形参为类的对象,当调用函数时,拷贝构造函数被调用
cout << B.GetR() << endl;
return 0;
}
⑶如果函数的返回值是类的对象,函数调用返回时,调用拷贝构造函数。
void fun2()
{
Circle A(10,5,5);
return A; // 返回值是类的对象,函数调用返回时,调用拷贝构造函数
}
int main()
{
Circle B;
B=fun2() ;
return 0;
}
例8-2-2 Circle 类的完整程序。
在程序主函数中,三个部分分别给出拷贝构造函数调用的三种情况。
//
// Chap8_2_2.cpp
//
#include <conio.h>
#include <iostream.h>
class Circle
{
public:
Circle(int rr=10,int xx=0,int yy=0) // 构造函数
{
R=rr;X=xx;Y=yy;
}
Circle(Circle &c); // 拷贝构造函数
int GetR() {return R;}
int GetX() {return X;}
int GetY() {return Y;}
private:
int R,X,Y;
static int i=0;
};
Circle::Circle(Circle &c) // 成员函数的实现
{
R = c.R;
X = c.X;
Y = c.Y;
i++;
cout << "拷贝构造函数被调用" << i << "次" << endl;
}
void fun1(Circle c) // 形参为Circle 类对象的函数
{
cout << "R=" << c.GetR() << endl;
}
// 返回值为Circle 类对象的函数
Circle fun2()
{
Circle A(10,5,5);
return A; // 返回值是类的对象,函数调用返回时,调用拷贝构造函数
}
// 主函数
void main()
{
Circle A(20,10,10);
Circle B(A); //情况一,用对象A 初始化对象B,第一次调用拷贝构造函数
cout << "R=" << B.GetR() << endl;
fun1(B); //情况二,对象B 作为fun1 的实参,第二次调用拷贝构造函数
B=fun2(); //情况三,fun2 的返回值赋给对象B,第三次调用拷贝构造函数
cout << "R=" << B.GetR() << endl;
getch();
}
程序运行结果为:
拷贝构造函数被调用1 次
R=20
拷贝构造函数被调用2 次
R=20
拷贝构造函数被调用3 次
R=10