目录
14.1 基本概念
重载运算符函数的参数数量与该运算符作用的运算对象数量一样多
14.2 输入和输出运算符
输入输出运算符必须是非成员函数
14.2.1 重载输出运算符<<
输出运算符的第一个形参是一个非常量ostream对象的引用,第二个形参一般是一个常量的引用,该常量是我们想要打印的类类型。operator<<一般返回他的ostream形参
ostream &operator<<(ostream &os,const Sales_data &item)
{
os<<item.isbn<<" "<<item.units_sold;
return os;
}
14.2.2 重载输入运算符>>
输入运算符的第一个形参是运算符将要读取的流的引用,第二个形参是将要读入到的对象引用,该运算符通常会返回某个给定流定引用,第二个形参之所以必须是个非常量是因为输入运算符本身的目的就是将数据读入到这个对象中。
istream &operator>>(istream &is,Sales_data &item)
{
double price;
is>>item.bookNo>>item.units_sold>>price;
if(is)
item.revenue=item.units_sold*price;
else
item=Sales_data(); //输入失败,对象被赋予默认状态
return is;
}
14.3 算术和关系运算符
算术运算符通常会计算他的两个运算对象并得到一个新值,该值常常位于一个局部变量支中,操作完成后返回该局部变量的副本作为其结果。
Sales_data operator+(const Sales_data &lhs,const Sales_data &rhs)
{
Sales_data sum=lhs;
sum+=rhs;
return sum;
}
14.3.1 相等运算符
相等运算符检验两个对象是否相等,比较对象中的每一个数据成员。
bool operator=(const Sales_data &lhs,const Sales_data &rhs)
{
return lhs.isbn()==rhs.isbn() &&
lhs.units_sold==rhs.units_sold &&
lhs.revenue==rhs.revenus;
}
bool operator!=(const Sales_data &lhs,const Sales_data &rhs)
{
return !(rhs==lhs);
}
14. 4 赋值运算符
class StrVec
{
public:
StrVec &operator=(std::initializer_list<std::string> il);
};
StrVec &StrVec::operator=(initializer_list<string> il)
{
auto data=alloc_ncopy(il.begin(),il.end());
free();
elements=data.first;
first_free=cap=data.second;
return *this;
}
复合赋值运算符
Sales_data &Sales_data::operator+=(const Sales_data &rhs)
{
units_sold+=rhs.units_sold;
revenue+=rhs.rhs.revenue;
return *this;
}
14.5 下标运算符
表示容器的类通常可以通过元素在容器的位置访问元素,这些类一般会定义下标运算符operator[]
下标运算符必须是成员函数
下标运算符所访问元素的引用作为返回值,好处是下标可以出现在赋值运算符的任意一端,且要定义常量版本和非常量版本,当作用于一个常量对象时,下标运算符返回常量引用确保不会给返回的对象赋值。
class StrVec
{
public:
string &operator[](size_t n){return elements[n]}
const string &operator[](size_t n) const {return elements[n];}
};
因为下标运算符返回的是元素的引用,所以当StrVec是非常量时,我们可以给元素赋值,而当我们对常量对象取下标时,不能为其赋值。
const StrVec cvec=svec //假定svec是一个StrVec
if(svec.size()&&svec[0].empty())
{
svec[0]="zero"; //正确,下标运算符返回string的引用
cvec[0]="zip"; //错误,对cvec取下标返回的是常量引用
}