(1)C++允许我们重新定义操作符用于类类型对象时的含义
(2)可以像内置转换一样使用类类型,将一个类型的对象隐式转换为另一个类型
标准库为容器定义了几个重载操作符:为容器定义了下标访问[],为迭代器定义了*和->
14.1 重载操作符的定义
重载操作符是具有特殊名称的函数:保留字operator后面接所需定义的操作符符号。
重载操作符的形参数目,与操作符的操作数相同。
不能重载的操作符 :: .* . ?:
不建议重载的操作符:&& || & ,
几个基本经验:
(1)重载操作符最好不要改变内置类型的含义
(2)操作符的优先级、结合性或操作符数目不能改变
(3)重载操作符并不保证求值顺序,例如最短路等
(4)多数重载操作符可以定义为普通成员函数或类的成员函数
(5)重载操作符有两种:作为类的成员、非类的成员,其中后面的版本比前面的少一个参数,即this参数内置,一般将算术和关系运算定义为非成员,赋值运算定义为成员。
(6)赋值(包括复合赋值如+=)一般返回类的引用,即左值;普通算术运算返回右值,即类类型。
(7)将操作符定义为非类成员的时候,一般要设置操作符为friend(在类内加friend就可以了),因为要访问private成员
如何调用重载操作符?
(1)和内置一样使用
cout<< item1+item2 <<endl;
(2)显示调用重载的符号函数
cout<< operator+(item1,item2) <<endl;
建议重载的操作符
因为STL算法需要部分操作符号的支持,所以建议重载下列操作符
(1)如果重载了==,也要重载!=
(2)sort等类似的算法需要重载小于号<
如何决定操作符为类成员还是非类成员
(1)赋值=,下标[],调用(),成员访问->必须定义为类成员,否则编译出错。
(2)复合赋值操作符通常应当定义为类成员
(3)改变对象状态或与给定类型密切联系的其他一些操作符,如++,--和引用&,通常应当定义为类成员
(4)对称的操作,如算术运算,相等运算,关系操作符,位操作符,最好定义为普通的非成员函数
14.2 输入和输出操作符
ostream & operator <<(ostream & os,const ClassType &object)
{
//把object的成员输出
os<<....;
return os;
}
ostream & operator >>(istream & is,ClassType &object)
{
//把输入从is读入到object的成员函数中
return is;
}
读入必须处理出错
输入操作符必须处理错误和文件结束的可能性。
(1)任何读操作都可能因为提供的值不正确而失败(数值/非数值导致错误)
(2)任何读入都可能碰到文件结束或者其他错误
关于(1)处理读入错误的办法是:把形参恢复为空的读入类型对象,可以设置failbit。
关于(2)指出错误的方法是:设置eofbit。
14.3 算术操作符和关系操作符
为了与内置操作符保持一致,加法应该返回右值,而不是引用(左值),这个已经反复强调的。
复合运算符号,例如+=,可以调用+来实现,而不必创建一个临时结果。
相等操作符
inline bool operator==(const ClassType &lhs,const ClassType &rhs)
{
return lhs.p1==rhs.p1 && lhs.p2==rhs.p2....
}
而重载operator !+的时候,可以return !(lhs==rhs);
<操作符
要谨慎对待,因为如果a<b且a>b,那么容器算法会认为a==b相等!
14.4 赋值运算符
注意:
(1)复合运算如+=也是赋值运算的一种
(2)赋值运算必须返回*this
ClassType& ClassType::operator+=(const ClassType &rhs)
{
this->val1+=rhs.val1;
return *this;
}
14.5 下标运算[]
注意,下标运算实际有两个版本,如下:
(1)a[3] = 10;
(2)cout << a[3];
(1)是[]返回了一个左值(引用)
(2)是[]返回了右值,右值是什么?就是const引用!
两个版本的重载函数原型如下:
class ClassType
{
public:
InnerType & operator [] (const size_t);
const InnerType & operator[] (const size_t);
private:
vector<InnerType> data;
未完待续。