拷贝构造函数
在C++中,除了可以使用构造函数直接创建一个新的对象之外,有时还需要根据已经存在的某个对象创建一个新的对象作为这个对象的副本。
在大多数情况下,默认的拷贝构造函数已经能够满足我们的需要了,但是有的时候,特别是类当中有指针类型的属性的时候,以拷贝内存形式实现的默认拷贝构造函数只能复制指针属性的值,而不能复制指针属性所指向的内存,在这种情况下,就需要自己定义类的拷贝构造函数,完成指针属性等需要特殊处理的属性的拷贝工作。例如,有一个Computer类,它有一个指针类型的属性m_pKeyboard指向它所连接的键盘。
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
//键盘类
struct Keyboard
{
//键盘型号
string m_strModel;
};
//定义了拷贝构造函数的电脑类
class Computer
{
public :
//默认构造函数
Computer()
: m_pKeyboard(NULL)
{}
//拷贝构造函数,参数是const修饰的Computer类的引用
Computer(const Computer& com)
: m_strModel(com.m_strModel) //对象类型的成员属性直接使用初始化列表
//完成拷贝
{
// 获得已有对象com的指针属性m_pKeyborad并赋值给pOldKeyboard
Keyboard* pOldKeyboard = com.GetKeyboard();
//以pOldKeyboard指向的Keyboard对象为蓝本,
//创建一个新的Keyboard类对象赋值给m_Keyboard属性
if (NULL != pOldKeyboard)
m_pKeyboard = new Keyboard(*(pOldKeyboard));
else
m_pKeyboard = NULL;
}
//省略析构函数
//成员函数
void SetKeyboard(Keyboard* pKeyboard)
{
m_pKeyboard = pKeyboard;
}
Keyboard* GetKeyboard() const
{
return m_pKeyboard;
}
private:
// 指针类型的成员属性
Keyboard* m_pKeyboard;
// 对象类型的成员属性
string m_strModel;
};
在这段代码中,我们为Computer类创建了一个自定义拷贝构造函数。在这个拷贝构造函数中,针对对象类型的成员属性,我们直接使用初始化列表就完成了属性的拷贝。而针对指针类型成员属性m_pKeyboard的拷贝,并不能直接采用内存拷贝的形式完成,那样只是拷贝了指针的值,而指针所指向的内容并没有得到拷贝。要完成指针类型成员属性的拷贝,首先应该获得已有对象的m_pKeyboard属性,也就是获得它所指向的Keyboard对象,然后以这个Keyboard对象为蓝本,利用Keyboard类的默认拷贝构造函数创建这个Keyboard对象的一个副本,最后将其地址赋值给m_pKeyboard属性,这样,这个拷贝构造函数不仅能够拷贝Computer类的对象类型成员属性m_strModel,也能够正确地完成指针类型成员属性m_pKeyboard的拷贝,最终才能完成Computer类的拷贝。
主函数代码:
#include "myHeader.h"
int main()
{
//创建一个Computer对象oldcom
Computer oldcom;
//创建oldcom的Keyboard对象并修改其属性
Keyboard keyboard;
keyboard.m_strModel = "Microsoft-101";
oldcom.SetKeyboard(&keyboard);
//利用Computer类的拷贝构造函数创建新对象newcom
//新的newcom对象是oldcom对象的一个副本
Computer newcom(oldcom);
//使用断言assert()判断两个Computer对象的m_pKeyboard属性不同,
//也就是它们分别指向两个不同的Keyboard对象,
//但是,这两个Keyboard对象的属性却是相同的
assert(newcom.GetKeyboard()!=oldcom.GetKeyboard());
assert(newcom.GetKeyboard()->m_strModel!=oldcom.GetKeyboard()->m_strModel);
return 0;
}