1. IO 操作符必须为非成员函数
为什么呢?因为我们不能将该操作符定义为类的成员函数,否则,左操作数将只能是该类类型的转换对象。
如果想要支持正常用法,则左操作数必须为 ostream 类型。这意味着,如果该操作符是类的成员,则它必须是 ostream 类的成员,然而,ostream 类是标准库的组成部分,我们是不能为标准库中的类增加成员的。
相反,如果想要使用重载操作符为该类型提供 IO 操作,就必须将他们定义为非成员函数。IO 操作符通常对非公用数据进行读写,因此,类通常将 IO 操作符设为友元。
2. 算术操作符和关系操作符
一般而言,将算术操作符和关系操作符定义为非成员函数。
Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)
{
Sales_item ret(lhs);
ret += rhs;
return ret;
}
加法操作符并不改变操作符的状态。为了与内置操作符保持一致,加法返回一个右值,而不是一个引用。
3. 相等操作符
如果定义了 operator==,应该也需要定义 operator!=。
4. 赋值操作符
赋值操作符可以重载。无论形参为何种类型,赋值操作符必须定义为成员函数。
Sales_item& Sales——item :: operator+=(const Sales_item& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
一般而言,赋值操作符与复合操作符应返回左操作数的引用。
5. 下标操作符
下标操作符必须定义为类成员函数。
6. 自增/自减操作符
C++ 不要求自增/自减操作符一定作为类的成员,但是,因为这些操作符改变操作对象的状态,所以更倾向于将他们作为成员。
6.1. 操作符的前缀形式
Checkedptr& Checkedptr :: operator++()
{
if(curr == end)
throw out_of_range("increament past the end of Checkedptr ");
++curr;
return *this;
}
Checkedptr& Checkedptr :: operator--()
{
if(curr == beg)
throw out_of_range("decreament past the beginning of Checkedptr ");
--curr;
return *this;
}
为了与内置类型一致,前缀式操作符应返回被增量或减量对象的引用。
6.2. 操作符的后缀形式
为了区别前缀操作符和后缀操作符,后缀式操作符函数接受一个额外的(即,无用的)int 型形参。使用后缀式操作符时。编译器提供 0 作为这个形参的实参。
Checkedptr Checkedptr :: operator++(int)
{
Checkedptr ret(*this);
++*this;
return ret;
}
Checkedptr Checkedptr :: operator--(int)
{
Checkedptr ret(*this);
--*this;
return ret;
}
为了与内置操作符一致,后缀式操作符应返回旧值(即,尚未自增或自减的值),并且,应作为值返回,而不是返回引用。