拷贝构造函数创建一个新的对象,此对象是另外一个对象的复制品:将原对象的数据成员逐一赋值给目标对象相应的数据成员。没有的话会自动生成一个默认构造函数。
// 原型(参数类型必须是引用)
Person(Person&);
或Person(const Person&);
// 如果有多个参数,第一个参数以后的所有参数必须有默认值
或Person(const Person&, bool married = false);
什么时候需要为类设计一个拷贝构造函数?
答: 当类中有指向动态分配内存空间的指针类型的数据成员时,则应该为类设计一个拷贝构造函数。
class Test
{
public:
Test(){ size = 0; p = 0; };
Test(const CString[], int);
void set(const CString&, int);
private:
int size;
CString* p;
};
Test::Test(const CString s[], int nSize)
{
size = nSize;
p = new CString[size];
for (int i = 0; i < size; i++)
{
p[i] = s[i];
}
}
void Test::set(const CString& s, int i)
{
p[i] = s;
}
CString s[] = { _T("aa"), _T("bb"), _T("cc") };
Test test1(s, 3);
Test test2(test1);
test2.set(_T("dd"), 1);
由于拷贝构造函数没有定义,故Test test2(test1)将会调用默认拷贝构造函数。而test2拷贝test1时,动态分配的内存并没有拷贝,只是拷贝了指向该内存空间的地址,故俩个对象的指针成员变量指向的是同一块内存。所以当改变test2的指针成员变量所指向的内容时,test1也随着改变。
为了让新对象也拥有自己的内存空间,需要设计一个拷贝构造函数。
Test(const Test&);
Test::Test(const Test& d)
{
delete[] p;
if (d.p != 0)
{
p = new CString[size = d.size];
for (int i = 0; i < size; i++)
{
p[i] = d.p[i];
}
}
else
{
p = 0;
size = 0;
}
}