运算符重载
Integer tmp(left.i + right.i);
重载时作为成员或非成员函数的选择:
所有的一元运算符 推荐作为成员
= () [] -> ->* 必须作为成员
+= -= /= *= ^=
&= |= %= >>= <<= 推荐作为成员
Fee fee(1);
Fee fum(fi);
这样的写法要比
Fee fee = 1;
Fee fum = fi;
重载的运算符必须接受至少一个自定义类型。接受的参数都为内置类型的运算符无法被重载。
运算符作为类的成员函数被重载时,类的对象就作为第一个参数。注意此时函数的返回方式。
重载++a会调用operator++(a),重载a++会调用operator++(a, int),其中第二个int参数是不会被用到的,只是用来区分前缀和后缀调用。--的重载也是一样。
->和->*也只能作为成员函数被重载,但对返回值有一定的限制。
.和.*不能被重载
Integer tmp(left.i + right.i);
return tmp;
重载时作为成员或非成员函数的选择:
所有的一元运算符 推荐作为成员
= () [] -> ->* 必须作为成员
+= -= /= *= ^=
&= |= %= >>= <<= 推荐作为成员
所有其他的二元运算符 推荐作为非成员
Fee fee(1);
Fee fum(fi);
这样的写法要比
Fee fee = 1;
Fee fum = fi;
这样的写法清晰。
在重载赋值运算符时,首先检查是否是对自身赋值是个好习惯。
当对象中有指针时,拷贝构造函数通常需要连同复制出指针所指向的内容。而当此内容很大时,通常采用引用计数的方法,只在需要修改数据且引用数大于1时才复制内容。这种技术被称为copy-on-write。
也可以重载operator 类型名来定义自动类型转换。由于这种类型转换是由源对象完成的(不像构造函数的类型转换是由目标对象完成的),因此可以完成自定义对象到内置类型的转换。
提供自动类型转换时注意两种类型之间只需提供一条转换路径,否则会出现二义性错误。
#include <iostream>
using namespace std;
template<typename T = int, size_t S = 3>
class Array
{
public:
// 重载[]运算符
T& operator [] (size_t num)
{
return m_arr[num];
}
// 提供一个常版本的[]运算符
T const& operator [] (size_t num) const
{
// 为了维护方便,尽量复用函数
return const_cast<Array&>(*this)[num];
}
int length(void) const
{
return S;
}
// 由于左操作数是标准提供的类,最好用友元的方式实现<<重载
friend ostream& operator << (ostream& os, Array const& arr)
{
for (size_t i = 0; i < S; ++i)
cout << arr[i] << ' ';
cout << endl;
}
private:
T m_arr[S];
};