首页 > 代码库 > 条款12:复制对象时请勿忘每一个成分

条款12:复制对象时请勿忘每一个成分

条款12:复制对象时请勿忘每一个成分
       当为一个类实现自己的构造函数,相关赋值函数,析构函数,则必须有责任对类中的每一个成员进行初始化、赋值、释放。因此:如果为一个类添加一个成员,就必须同时相应修改上面几类函数。
看一个简单的类
class Terminal
{
	Terminal(const int termid) : m_termId(termid) {}

	~Terminal() {}

	Terminal(const Terminal & terminal)
	{
		this->m_termId = terminal.m_termId;
	}

	Terminal & operator = (const Terminal &terminal)
	{
		if (this != &terminal) {
			this->m_termId = terminal.m_termId;
		}

		return *this;
	}
private:
	int m_termId;
};
为Terminal类新增加一个成员m_name后,对应的函数如下修改
class Terminal
{
public:
	Terminal() : m_termId(0), m_name(NULL) {}
	Terminal(const int termid, const char* name) : m_termId(termid) 
	{
		if (name == NULL) {
			this->m_name = new char[1];
			*this->m_name = '\0';
		}

		this->m_name = new char[strlen(name) + 1];
		strcpy(this->m_name, name);
	}

	~Terminal() 
	{ 
		if (m_name != NULL)
			delete m_name;
		m_name =NULL;
	}

	Terminal(const Terminal & terminal)
	{
		this->m_termId = terminal.m_termId;
		this->m_name = new char[strlen(terminal.m_name) + 1];
		strcpy(this->m_name, terminal.m_name);
	}

	void Swap(Terminal& terminal)   //自定义swap,避免重分配内存
	{
		std::swap(this->m_termId, terminal.m_termId);
		std::swap(this->m_name, terminal.m_name);
	}

	Terminal & operator = (Terminal terminal)
	{
		Swap(terminal);
		return *this;
	}
private:
	int m_termId;
	char *m_name;
};
在继承类中如何去复制每一个成员呢?
class TcpTerminal : public Terminal
{
public:
	TcpTerminal(const int type) : m_type(type) {}
	TcpTerminal(const TcpTerminal & rhs) : m_type(rhs.m_type) {}
	TcpTerminal & operator = (const TcpTerminal &rhs)
	{
		if (this != &rhs)
			this->m_type = rhs.m_type;
		
		return *this;
	}

private:
	int m_type;
};
此继承类实现出现有如下问题
TcpTerminal tcp(2); //调用基类Terminal的默认构造函数初始化继承的基类成员
TcpTerminal tcp2(tcp);  //调用基类Terminal的默认构造函数初始化继承的基类成员,如果tcp对象基类成员有值,经过拷贝tcp2中基类成员没有得到赋值
tcp = tcp2;  //没有对基类成员赋值,则还是保留原来的基类成员
修改上面的代码实现对基类成员的拷贝
class TcpTerminal : public Terminal
{
public:
	TcpTerminal(const int type, const int termId, const char* name) : Terminal(termId, name), m_type(type) {}
	TcpTerminal(const TcpTerminal & rhs) : m_type(rhs.m_type), Terminal(rhs) {}
	TcpTerminal & operator = (const TcpTerminal &rhs)
	{
		if (this != &rhs) {
			this->m_type = rhs.m_type;
			Terminal::operator = (rhs);
		}
		
		return *this;
	}

private:
	int m_type;
};
调用如下
	TcpTerminal tcp(2, 3, "tcp"); 
	TcpTerminal tcp2(tcp);  
	TcpTerminal tcp3(4, 5, "tcp3");
	tcp = tcp3; 
当为一个类实现copy函数时,需记住以下两点
(1)拷贝local成员变量
(2)调用base class捏的适当的copying函数

记住
①要确保拷贝函数拷贝对象的所有的数据成员,及其基类的所有部分,不要有遗漏。
②不要尝试去实现一个拷贝函数来供其它的拷贝函数调用。取而代之的是,把公共部分放入一个“第三方函数”中共所有拷贝函数调用。