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