复制构造函数是构造函数的一种,也称拷贝构造函数,它只有一个参数,参数类型是本类的引用。
复制构造函数的参数可以是 const 引用,也可以是非 const 引用。 一般使用前者,这样既能以常量对象(初始化后值不能改变的对象)作为参数,也能以非常量对象作为参数去初始化其他对象。一个类中写两个复制构造函数,一个的参数是 const 引用,另一个的参数是非 const 引用,也是可以的。
如果类的设计者不写复制构造函数,编译器就会自动生成复制构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认复制构造函数”。
注意,默认构造函数(即无参构造函数)不一定存在,但是复制构造函数总是会存在。
下面是一个复制构造函数的例子。
#include<iostream >
using namespace std;
class Complex
{
public:
double real, imag;
Complex(double r, double i) {
real= r; imag = i;
}
};
int main(){
Complex cl(1, 2);
Complex c2 (cl); //用复制构造函数初始化c2
cout<<c2.real<<","<<c2.imag; //输出 1,2
return 0;
}
第 13 行给出了初始化 c2 的参数,即 c1。只有编译器自动生成的那个默认复制构造函数的参数才能和 c1 匹配,因此,c2 就是以 c1 为参数,调用默认复制构造函数进行初始化的。初始化的结果是 c2 成为 c1 的复制品,即 c2 和 c1 每个成员变量的值都相等。
如果编写了复制构造函数,则默认复制构造函数就不存在了。下面是一个非默认复制构造函数的例子。
#include<iostream>
using namespace std;
class Complex{
public:
double real, imag;
Complex(double r,double i){
real = r; imag = i;
}
Complex(const Complex & c){
real = c.real; imag = c.imag;
cout<<"Copy Constructor called"<<endl ;
}
};
int main(){
Complex cl(1, 2);
Complex c2 (cl); //调用复制构造函数
cout<<c2.real<<","<<c2.imag;
return 0;
}
程序的输出结果是:
Copy Constructor called
1,2
第 9 行,复制构造函数的参数加不加 const 对本程序來说都一样。但加上 const 是更好的做法,这样复制构造函数才能接受常量对象作为参数,即才能以常量对象作为参数去初始化别的对象。
第 17 行,就是以 c1 为参数调用第 9 行的那个复制构造函数初始化的。该复制构造函数执行的结果是使 c2 和 c1 相等,此外还输出Copy Constructor called。
可以想象,如果将第 10 行删去或改成real = 2*c.real; imag = imag + 1;,那么 c2 的值就不会等于 c1 了。也就是说,自己编写的复制构造函数并不一定要做复制的工作(如果只做复制工作,那么使用编译器自动生成的默认复制构造函数就行了)。但从习惯上来讲,复制构造函数还是应该完成类似于复制的工作为好,在此基础上还可以根据需要做些別的操作。
构造函数不能以本类的对象作为唯一参数,以免和复制构造函数相混淆。例如,不能写如下构造函数:
Complex (Complex c) {...}