《C++ Primer 4 Answer Book》 整理[13]——第14章 重载操作符与转换


14   重载操作符与转换

        9514.1在什么情况下重载操作符与内置操作符不同?在什么情况下重载操作符与内置操作符相同?

        答:重载操作符与内置操作符的不同之处在于:重载操作符必须具有至少一个类类型或枚举类型的操作数;重载操作符不保证操作数的求值顺序,例如,&&||的重载版本就失去了“短路求值“特性,两个操作数都要进行求值,而且不规定操作数的求值顺序。

        重载操作符与内置操作符的相同之处在于:操作符的优先级、结合性及操作数数目均相同。

        

        9614.2Sales_item编写输入、输出,加以及复合赋值操作符的重载声明

        答:Class Sales_item{

                           friendstd::istream& operator>> (std::istream&,Sales_item&);

                           friendstd::ostream& operator<< (std::ostream&,const Sales_item&);

                  public:

                           Sales_item&operator+=(const Sales_item&);

                  };

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

        其中,复合赋值操作符定义为public成员,输入和输出操作符需要访问Sales_item类成员,所以需定义为Sales_item类的友元。加操作符可以用public成员+=来实现,所以无需定义为Sales_item类的友元。

 

        9714.5列出必须定义为类成员的操作符

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

        

        9814.6解释下面操作符是否应该为类成员,为什么?

        +--++><<&&==()

        答:+<<==操作符通常应定义为非成员函数,但<<操作符通常需要访问类的数据成员,所以一般应指定为类的友元;

        --++会改变对象的状态,通常应定义为类成员;

        ->()必须定义为类成员,否则会出现编译错误;

        &&一般对类类型操作数没有意义,通常不进行重载;如果一定要重载,可重载为非成员函数;

 

        9914.8定义Date类的输出操作符

        答: ostream& operator <<(ostream& out,const Date d)

                  {

                           out<

                           returnout;

                  }

        注意,应将<<操作符指定为Date类的友元。

        

        10014.14定义一个赋值操作符,将isbn复制给Sales_item对象

        答:Sales_item& Sales_item::operator(conststring& str)

                  {

                           isbn=str;

                           return*this;

                  }

                  注意,赋值操作符必须定义为类的成员函数,且一般应返回左操作数的引用。

        

        10114.17CheckoutRecord类定义一个下标操作符,从等待列表中返回一个名字。

        答:pair&CheckoutRecord::operator[](const vector< pair*>::size_type index)

                  {

                           return*wait_list.at(index);  //使用at可检查下标是否越界

                  }

                  

                  constpair& CheckoutRecord::operator[](const vector* >::size_type index) const

                  {

                           return*wait_list.at(index);

                  }

                  注意,下标操作符必须定义为类成员函数,且返回引用以便可以用在赋值操作符的任意一边。类定义下标操作符时,一般需定义两个版本,即返回引用的非const成员及返回const引用的const成员,以便可以对const和非const对象使用下标;可以对下标是否越界进行检查(这与内置下标操作符的语义有所不同),以避免对内存的非法访问。

 

        10214.21定义一个类,该类保存一个指向ScreenPtr的指针。为该类定义一个重载的箭头操作符。

        答:class NoName{

                  public:

                           NoName(Screen*p):ptr(new ScreenPtr(p)){}

                           ScreenPtroperator->()

                           {

                                    return*ptr;

                           }

                           constScreenPtr operator->() const

                           {

                                    return*ptr;

                           }

 

                  private:

                           ScreenPtr*ptr;

                  };

                  注意,箭头操作符必须定义为类成员函数,重载的箭头操作符不接受显式形参,且必须返回指向类类型的指针,或者返回定义了箭头操作符的类类型对象;需要定义箭头操作符的const和非const版本,以便可以对const和非const对象使用箭头操作符。

        

        10314.41解释这两个转换操作符之间的不同

        classintegral{

        public:

                  operatorconst int() const;

                  operatorint() const;

        }

        这两个转换操作符是否太严格了?如果是,怎样使得转换更通用一些?

        答:这两个转换操作符之间的不同之处在于:前者将对象转换为const int值(intconst变量),而后者将对象转换为int值(int型变量);前者太严格了,只能用于可以使用const int值的地方,将前者去掉只保留后者,即可使得转换更为适用。(事实上,如果这两个转换操作符同时存在,则在既可使用intconst变量又可使用int型变量的情况下,会因编译器无法作出抉择而产生错误)。

        

        10414.44为下述每个初始化列出可能的类类型转换序列。每个初始化的结果是什么?

        classLongDouble{

        public:

                  operatordouble();

                  operatorfloat();

        };

        LongDoubleidObj;

        a)intex1=idObj;    b)floatex2=idObj;

        答:a)有二义性,因为既可以先使用从LongDoubledouble的转换操作,再使用从doubleint的标准转换,也可以先使用从LongDoublefloat的转换操作,再使用从floatint的标准转换,二者没有优劣之分。

        b)使用从LongDoublefloat的转换操作,将idObj对象转换为float值用于初始化ex2

 

        10514.45哪个calc()函数是如下函数调用的最佳可行函数?列出调用每个函数所需的转换序列,并解释为什么所选定的就是最佳可行函数?

        classLongDouble{

        public:

                  LongDouble(double);

                  ……

        };

        voidcalc(int);

        voidcalc(LongDouble);

        doubledval;

        calc(dval);//which function?

        答:最佳可行函数为void calc(int)。调用void calc(int)所需的转换为:将实参dvaldouble类型转换为int类型(标准转换);

        调用void calc(LongDouble所需的转换为:将实参dvaldouble类型转换为LongDouble类型(使用LongDouble类的构造函数,为类类型转换);

        因为标准转换优于类类型转换,所以void calc(int)为最佳可行函数。

 

你可能感兴趣的:(C++语法,架构,内部机制)