十四章、重载操作符

十四章、重载操作符

一、重载操作符的定义: 保留字operator后接需要定义的操作符符号,同时具有返回类型和形参表;如:Sales_item operator+ (const Sales_item&,const Sales_item&);

1、  除了函数调用操作符之外,重载操作符的形参数目与操作符的操作数数目相同,函数调用操作符可以接受任意数目的操作符。

2、  重载操作符必须具有一个类类型操作数,内置类型的操作符其含义不能改变;(重载操作符必须具有至少一个类类型或枚举类型)

3、  作为类成员的重载函数,有一个隐含的this形参,限定为第一个操作数(左操作数)。

4、  Cout << item1 + item2 << endl; 这个表达式隐式调用了Sales_item operator+

5、  重载操作符的设计:不要重载具有内置含义的操作符

(1)       合成赋值操作符进行逐个成员赋值

(2)       默认情况下,取地址操作符(&)和逗号操作符(,)在类类型对象上的执行与在内置类型对象上的执行一样。

(3)       内置逻辑与(&&)和逻辑或(||)使用短路求值,如果重新定义该操作符,将失去操作符的短路求值特征。

6、  为类设计操作符,最好的方式是首先设计类的公用接口。定义了接口之后就可以考虑将那些操作符定义为重载操作符。如:

  • ·相等测试操作应使用operator == ;
  • ·一般通过重载一位操作符进行行输入和输出;
  • ·测试对象是否为空的操作可以用逻辑非操作符operator!表示。

7、  选择成员或非成员师兄:

·赋值(=)、下标([])、调用(())和成员访问箭头(->)等操作符必须定义为成员。

·复合赋值操作符通常定义为类的成员。

·自增或自减和解引用通常定义为类成员。

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

二、输入和输出操作符:为了与IO标准库一致,操作符应接受ostream&/istream&作为顶一个形参,对类类型const对象的引用作为第二个行程,并返回ostream/istream形参的引用。

1、  salse_item的输出操作符:

  • ostream& operator<<(ostream& out,const Sales_item& s)

{

Out << s.isbn << “\t” << s.units_sold << “\t” << s.revenue << “\t” << s.avg_price() ;

Return out ;

}

(如果IO操作符是类成员,则左操作数将智能是该类类型的对象,所以必须为非成员函数,同时,类通常将IO操作符设为友元)

2、  输入操作符 >> 重载:Sales_item 的输入操作符

Istream& operator>> (istream& in ,Sales_item& s)

{

         Double price;

         In >> s.ibsn >> s.units _sold >> price ;

         If (In)

                   s.revenue = s.units_sold * price ;

         else

                   s = Sales_item() ; 

}

输入期间的错误:

(1)       任何读操作都可能因为提供的值不正确而失败。如读入isbn之后,输入操作符将期望下两项是数值型数据。如果输入非数值型数据,这次的读入以及流的后续将都是失败。

(2)       任何读入都可能碰到输入流中的文件结束或其他一些错误。

如果有错,具体做法是创建一个新的、未命名的、使用默认构造函数的Sales_item对象并将它赋值给s。赋值后,s的isbn是空string,revenue和units_sold为0.

三、算术操作符和关系操作符:一般,将算术和关系操作符定义为非成员函数。

1、  相等操作符:

Inline bool operator==(const Sales_item &lhs,const  Sales_item &rhs)

{

Return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue &&

lhs.same_isbn(rhs) ;

}

Inline bool operator!=(const Sales_item &lhs, const Sales_item &rhs)

{

 Return !(lhs == rhs) ;

}

函数所包含的设计原则:

  • ·如果类定义了==操作符,该操作符的含义是两个对象包含同样的数据。
  • ·如果类具有一个操作,能确定该类型的两个对象是否相等,通常将该函数定义为operator==,而不是创造命名函数。
  • ·如果类定义了operator==,应该也定义operator!=
  • ·相等和不相等操作符一般应该联系定义。一个完成对象操作,另一个只需要调用前者。如上面函数。

四、赋值操作符: 赋值操作符必须定义为成员函数,必须返回对*试试的引用!

五、下标操作符:类定义下标操作符时,一般需要两个版本:一个非const成员的返回引用,另一个const成员的返回const引用!

1、  原型下标操作符: 简化,假定Foo所保存的数据储存在一个vector<int>中:

Class Foo

{

         Public:

                   Int  &operator[] (const size_t);

Const  Int  &operator[] (const size_t)const ;

                   Private:

                            Vector<int> data;

}

下标操作符:

Int & Foo::operator[] (const size_t index)

{

 Return data[index] ;

}

Const int & Foo::operator[](const size_t index) const

{

         Return data[index] ;

}

六、自增和自减操作符

1、    ++I ,--I 形式:

声明形式:

Class CheckedPtr

{

         Public:

                   CheckedPtr& operator++();

                   CheckedPtr& operator- -();

} ;

函数具体形式:

CheckedPtr& CheckedPtr::operator++()

{

         If(curr == end)

                   Throw out_of_range(”increment past the end of CheckedPtr”);出错处理

         ++cuur ;

         Return *this ;

}      // ++i

 

CheckedPtr& CheckedPtr::operator--()

{

         If(curr == end)

                   Throw out_of_range(”increment past the end of CheckedPtr”);出错处理

         --cuur ;

         Return *this ;

}      // --i

2、    i++ / i—形式:

声明形式:

Class CheckedPtr

{

         Public:

                   CheckedPtr& operator++(int);

                   CheckedPtr& operator- -(int);

} ;

为了区分++i和i++,将重载操作符函数增加了一个无用的int形参,一般可以传一个0进来。

此时操作符应该返回旧值(尚未自增,自减的值),是值返回,而不是返回引用。

CheckedPtr& CheckedPtr::operator++(int)

{

         CheckedPtr ret(*this)         ;

++*this ;

         Return ret ;

}      //  i++

 

CheckedPtr& CheckedPtr::operator--(int)

{

         CheckedPtr ret(*this)         ;

--*this ;

         Return ret ;

}      //  i--

 

posted @ 2012-07-18 16:01  欢_全力以赴  阅读(179)  评论(0编辑  收藏  举报