运算符重载与复制构造函数
其实也不是什么原创,网上查的资料,具体在哪里查的不记得了,在此感谢他们。
1运算符重载operator
1.1基本规则
1.一元操作符可以是不带参数的成员函数[1]或带一个参数的非成员函数[1]。
2.二元操作符可以是带一个参数的成员函数[1]或带两个参数的非成员函数[1]。
3.operator=、operator[]、operator()、operator->只能定义为成员函数[1]。
4.operator->的返回值必须是一个指针或能使用->的对象。
5.重载 operator++ 和 operator-- 时带一个 int 参数表示后缀,不带参数表示前缀。
6.除 operator new 和 operator delete 外,重载的操作符参数中至少要有一个非内建数据类型。
7.x@y 搜索范围为:x 成员函数--> 全局函数/X所在名字空间中的函数/Y所在名字空间中的函数/X的友元函数/Y的友元函数。
8.重载的的操作符应尽量模拟操作符对内建类型的行为。
1.2重载符的建议
1.只将会改变第一个参数的值的操作符(如: +=)定义为成员函数,而将返回一个新对象的操作符(如: +)定义为非成员函数(并使用 += 来实现)。
2.只有非成员函数才能在左参数上实施性别转换,如果需要进行转换则应将操作符定义为非成员函数。
3.对一元操作符, 为避免隐式转换最好将其重载为成员函数。
4.对二元操作符, 为能在左操作数上能进行和右操作数一样的隐式转换, 最好将其重载为非成员函数。
5.为了遵照使用习惯,operator>>、operator<< 应定义为非成员函数。
6.重载 operator[] 之类的操作符, 应尽量提供 const 版本和非 const 版本。
7.关于将操作符定义为成员或非成员可参考以下建议:
操作符建议所有一元操作符成员 = () [] -> 必须为成员 += -= /= *= ^= &= != %= >>= <<= 成员其它二元操作符非成员
8.如果默认操作符已经可以施用于你的型别上, 则应尽量避免重载此操作符. 如 operator, 、operator&(取地址) 等等.
1.3重载符的调用
如果调用成员函数,符号左边的对象表示this指针。
如果调用非成员函数,符号左边的对象表示该函数的第一个参数。
2复制构造函数
系统默认的复制构造函数是值传递。
当类变量有需要动态分配类存的指针时,一定要自写复制构造函数,即使不用复制构造函数来生成新对象。否则也会发生不可预知的问题,
例:
class Ctest
{
public:
Ctest(char * pMsg)
{
m_pMsg = new char[strlen(pMsg)+1];
strcpy(m_pMsg, pMsg);
m_pMsg[strlen(pMsg)] = ‘\0’;
}
void ShowMsg(Ctest test)
{
cout << test.m_pMsg << endl;
}
~Ctest()
{
if(m_pMsg != NULL)
{
delete []m_pMsg;
m_pMsg = NULL;
}
}
char * m_pMsg;
}
当调用ShowMsg函数时,函数用系统默认的复制构造函(值传递)数生成一个副本,这个副本和改对象的m_pMsg指向同一个地址,当该函数执行完成后,副本对象被释放,调用析构函数,m_pMsg的内存释放,再次调用ShowMsg时,出现异常。所以一定要重新写构造函数,而构造函数的形式只能为:
T(const T & pT); //const防止T自身重复循环被构造。
3 operator=与复制构造函数的区别
operator= 与复制构造函数的调用都可以写成这样:
Ctest test; //Ctest表示一个类
Ctest test2 = test;//表示调用复制构造函数,是Ctest test2(test)的简写。
Ctest test3;
test3 = test;//表示调用operator=