第十四章 重载操作符与转换

第十四章 重载操作符与转换

1.重载操作符的定义

重载操作符是具有特殊名称的函数:保留字operator后接需定义的操作符符号。重载操作符具有返回类型和形参表,如:

Sales_item operator+(const Sales_item&,const Sales_item&);

声明加号操作符,可用于将两个Sales_item对象相加并获得一个Sales_item对象的副本

1.1重载操作符必须具有一个类类型操作数

用于内置类型的操作符,其含义不能改变,如,内置的整型加号操作不能重定义:

int operator+(int,int);//error

1.2优先级和结合性是固定的

操作符的优先级、结合性或操作数数目不能改变。

不管操作数的类型和操作符的功能定义如何,x==y+z; 总是将实参y和z绑定到operator+,并将结果用作operator==的右操作数

1.3不再具备短路求值特性

重载操作符不保证操作数的求值顺序,尤其是,不会保证内置逻辑AND、逻辑OR和逗号操作符的操作数求值

1.4使用重载操作符

使用重载操作符的方式,与内置类型操作数上使用操作符的方式一样。假定item1和item2是Sale_item对象,可以打印他们的和,就像打印两个int的和一样:

cout << item1 + item2 << endl;

2.重载操作符的设计

2.1不要重载具有内置含义的操作符

重载逗号、取地址、逻辑与、逻辑或等操作符通常是不好的做法,这些操作符具有有用的内置含义,若定义了自己的版本,就不能再使用这些内置含义。

2.2大多数操作符对类对象没有意义

设计类的时候,应该确定要支持哪些操作符。那些逻辑上可以映射到某个操作符的操作可以考虑作为候选的重载操作符,如:

  • 相等测试操作应使用operator==

  • 一般通过重载移位操作符进行输入和输出、

  • 测试对象是否为空的操作可用逻辑非操作符operator!表示

2.3选择成员或非成员实现

  • 赋值(=)、下标([])、调用(())和成员访问箭头(->)等操作符必须定义为成员,将这些操作符定义为非成员函数将在编译时标记为错误

  • 像赋值一样,复合赋值操作符通常应定义为类的成员。与赋值不同的是,不一定非得这样做,如果定义非成员复合赋值操作符,不会出现编译错误。

  • 改变对象状态或与给定类型紧密联系的其他一些操作符,如自增、自减和解引用,通常应定义为类成员。

  • 对称的操作符,如算术操作符、相等操作符、关系操作符和位操作符,最好定义为普通非成员函数。

3.输入和输出操作符

3.1输出操作符<<重载

3.1.1Sales_item输出操作符

编写Sales_item的输出操作符:

ostream& opertor<<(ostream& out,Sales_item& s)
{
    out << s.isbn<<"\t"<<s.units_sold<<"\t"<<s.revenue<<"\t"<<s.avg_price();
    return out;
}

输出Sales_item,就需要输出它的三个数据成员以及计算得到的平均销售价格,每个成员用制表符间隔。输出值之后,该操作符返回所写ostream对象的引用。

3.2IO输入操作符>>的重载

输入操作符的第一个形参是一个引用,指向它要读的流,并返回的也是同一个流的引用。它的第二个形参是对要读入的对象的非const引用,该形参必须为非const,因为输入操作符的目的是将数据读到这个对象中。

3.2.1 Sales_item的输入操作符

Sales_item输入操作符如下:

istream& operator>>(istream& in,Sales_item& s)
{
    double price;
    in >> s.isbn>>s.units_sold>>price;
    if(in)//检查错误
        s.reven=s.units_sold * price;
    else
        s=Sales_item();
    return in;
}

这个操作符从istream形参中读取三个值:一个string值,存储到Sales_item形参的isbn成员中,一个unsigned值,存储到Sales_item形参的units_sold成员中;一个double值,存储到Sales_item形参的price成员中。假定读取成功,操作符用price和units_sold来设置Sales_item对象的reven成员

3.2.2输入期间的错误

Sales_item的输入操作符将读入所期望的值并检查是否发生错误。

(1)任何读操作都可能因为提供的值不正确而失败。

(2)任何读入都可能碰到输入流中的文件结束或其他一些错误,如下为错误检查

 if(in)//检查错误
        s.reven=s.units_sold * price;
    else
        s=Sales_item();

猜你喜欢

转载自blog.csdn.net/zhangxiafll/article/details/81631261