C++ Primer 【第四版】第十四章 重载操作符与转换

来源:互联网 发布:高一数学优化方案答案 编辑:程序博客网 时间:2024/06/06 00:00
1。在什么情况下重载操作符与内置操作符不同?在什么情况下重载操作符与内置操作符相同?

重载操作符必须具有至少一个类类型或枚举类型的操作数。重载操作符不保证操作数的求值顺序,例如对 && ||的重载版本不再具有“短路求值”的特性,两个操作数都要进行求值,而且不规定操作数的求值顺序。

对于优先级和结合性及操作数的数目都不变。

 

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

class Sales_item

{

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

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

public:

      Sales_item& operator += ( constSales_item& );

};

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

 

 

 

3。解释如下程序,假定Sales_item构造函数的参数是一个string,且不为explicit.解释如果构造函数为explicit会怎样。

string null_book = “0-000-00000-0”;

Sales_item item(cin);

item += null_book;

第一句:调用接受一个C风格的字符串形参的string构造函数,创建一个string临时对象,然后使用string复制构造函数用这个临时对象初始化string对象null_book,

第二句:从标准输入设备读入数据,创建Sales_item对象item

第三句:首先调用接受一个string参数的Sales_item构造函数,创建一个临时对象,然后调用Sales_item的复合重载操作符+=,将这个Sales_item临时对象加到item对象上,

如果构造函数为explicit,则不能进行从string对象到Sales_item对象的隐式转换,第三句将不能被编译。

 

4stringvector类都定义了一个重载的==,可用于比较这些类的对象,指出下面的表达式中应用了哪个==版本。

string s; vector<string> svec1,svec2;

“cobble” == “store” 应用了C++语言内置版本的重载==

svec1[0] == svec2[0];应用了string版本的重载==

svec1 == svec2     应用了vector版本的重载==

 

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

赋值 =下标[]调用 (),成员访问箭头 ->

 

 

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

a+  (b) +=  (c)++  (d) ->  (e) << (f) &&  (g) == (h) ( )

+, <<, ==&&通常定义为非成员;->()必须定义为成员,否则会出现编译错误;+= ++会改变对象的状态,通常会定义为类成员。

 

7。为下面的ChecoutRecord类定义一个输出操作符:

class CheckoutRecord

{

public:

// ..

private:

      doublebook_id;

      stringtitle;

      Datedate_borrowed;

      Datedate_due;

      pair<string,string>borrower;

      vector<pair<string, string>* > wait_list;

};

 

ostream&

operator << (ostream&out, const CheckoutRecord& s)

{

         out << s.book_id << "\t"<<s.title<<"\t" <<s.date_borrowed<<"\t" <<s.date_due

                           <<  "\t";

         out<< "borrower:" <<s.borrower.first<<"," << s.borrower.second <<endl;

         out << "wait_list: " << endl;

         for ( vector< pair<string,string>* >::const_iteratorit =s.wait_list.begin();

                                    it != s.wait_list.end(); ++it )

         {

                   out << "\t" << (*it)->first <<","<< (*it)->second<<endl;

         }

         return out;

}

 

8。在12.4节的习题中,你编写了下面某个类的框架: (b) Date

为所选择的类编写输出操作符。

#include<iostream>

using namespace std;

 

class Date

{

public:

      Date() {}

      Date( int y, int m, int d )

      {

             year = y;   month = m; day = d;

      }

      friend ostream& operator<< (ostream&, const Date& );

private:

      int year, month, day;

};

ostream&

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

{

      out << " year: " <<d.year << "\t"

             << " month: "<< d.month << "\t"

             << " day: "<< d.day << endl;

}

int main()

{

   Date dt(1988, 12, 01);

   cout << dt << endl;

   system("pause");

   return 0;

}

 

 

9。给定下述输入,描述Sales_item输入操作符的行为。

(a) 0-201-99999-9  10   24.95

(b) 10  24.95   0-201-99999-9

(a)0-201-99999-9读入赋给对象的isbn成员,将10units_sold成员,revenue成员被设置为249.5

(b)首先将形参对象的isbn成员设置为10,然后因为输入的数据不符合要求,导致输入失败,从而执行else语句,将Sales_item对象复位为空对象,此时isbn为空stringunits_soldrevenue都为0

 

 

10。下述Sales_item输入操作符有什么错误?

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

{

      doubleprice;

      in>> s.isbn >> s.units_sold >> price;

      s.revenue= s.units_sold * price;

      returnin;

}

如果将习题14.9中的数据作为输入,将会发生什么?

上述的输入操作符中缺少了对错误输入情况的判断与处理,会导致错误的情况发生。

(a)的输入没有问题,但是(b)的输入,将形参Sales_item对象的ISBN成员值为10,units_soldrevenue成员保持原值不变。

 

11。为14.2.1节习题中定义的CheckoutRecord类定义一个输入操作符,确保该类操作符处理输入错误。

classCheckoutRecord

{

public:

        // …

        friend istream&operator>>(istream&,CheckoutRecord&);  // 声明为类的友元

// …

};

istream &operator>> (istream&in,CheckoutRecord&c)

{

           cout << "Input bookid(double) and title(string) :\n";

           in >> c.book_id >>c.title;

 

                  //Input Data data_borrowed and data_due

                  cout<< " Input data_borrowed (3 ints: year,month , day) :\n";

                  in>> c.date_borrowed;//.year >> c.date_borrowed.month >>c.date_borrowed.day;

                  //Input Data data_due and data_due

                  cout<< " Input data_due (3 ints: year, month, day) :\n";

                  in>> c.date_due;//.year >> c.date_due.month >> c.date_due.day;

 

                  //Input the pair<string,string> borrower

                  cout<< " Input the pair<string,string>borrower (string) :\n";

                  in>> c.borrower.first >>c.borrower.second;         

                  if( !in )

                  {       

                           c = CheckoutRecord();

                            return in;

                  }

 

                  //Input wait_list

                  cout<< " Input the wait_list (string):\n";

                  c.wait_list.clear();

                  while( in )

                  {

                           pair<string,string> *ppr = new pair<string,string>;

                           in >>  ppr->first>>ppr->second;

                           if ( !in )

                           {       

                                    delete ppr;

                                    return in;

                           }

                           c.wait_list.push_back(ppr );

                  }       

                  

         return in;

}

输入错误的情况:

 

输入正确的情况:

 

 

 

12。编写Sales_item操作符,用+进行实际加法,而+=调用+。与本节中操作符的实现方法相比较,讨论这个方法的缺点。

Sales_itemSales_item::operator+( const Sales_item& rhs )

{

      units_sold += rhs.units_sold;

      revenue += rhs.revenue;

      return *this;

}

 

将下面定义的非成员+=操作符声明为类Sales_item的友元:

Sales_itemoperator+=( Sales_item& lhs, const Sales_item& rhs )

{

      lhs = lhs + rhs;

      return lhs;

}

这个方法缺点:在+=操作中需要创建和撤销一个临时Sales_item对象,来保存+操作的结果,没有本节中的方法简单有效。

 

 

13。如果有,你认为Sales_item还应该有哪些其他的算术操作符?定义你认为的该类应包含的那些。

还应有-操作符,定义为类的非成员,相应地还应该有-=复合操作符并定义为类的成员。

Sales_item&Sales_item::operator-=( const Salse_item& rhs )

{

      units_sold -= rhs.units_sold;

      revenue -= rhs.revenue;

      return *this;

}

Sales_item operator-(const Sales_item &lhs, const Sales_item & rhs )

{

      Sales_item ret(lhs);

      ret -= rhs;

      return ret;

}

 

14。定义一个赋值操作符,将isbn赋值给Sales_item对象。

Sales_item&Sales_item::operator=( const string & s )

{

      sbn = s;

      return *this;

}

 

 

10。为14.2.1节习题中介绍的CheckoutRecord类定义赋值操作符。

主函数中定义了两个CheckoutRecord类的对象,调用了CheckoutRecord类的 =赋值操作符,效果如下截图:

int_tmain(int argc, _TCHAR* argv[])

{

        CheckoutRecordc1;

        cin>> c1;

        CheckoutRecordc2;

        c2 = c1;  // 调用了类的赋值操作符=

        std::cout <<c2<< std::endl;//输出对象c2的内容

 

        system("pause");

        return0;

}

 

// CheckoutRecord类中赋值操作符定义为:

//重载操作符=

CheckoutRecord&CheckoutRecord::operator =(const CheckoutRecord&cr)

{

        book_id= cr.book_id;

        title= cr.title;

        date_borrowed= cr.date_borrowed;//前提:必须在Date类里也重载操作符=

        date_due= cr.date_due;          //  as before

        // pair进行赋值操作

        borrower.first =cr.borrower.first;

        borrower.second =cr.borrower.second;

 

        // vector进行赋值操作

        wait_list.clear();// 首先清空

        for ( vector<pair<string,string>*>::const_iteratorit= cr.wait_list.begin();

                                              it != cr.wait_list.end(); ++it )

        {

                  pair<string,string>*ppr = new pair<string,string>;

                  ppr->first = (*it)->first;

                  ppr->second = (*it)->second;

                  wait_list.push_back(ppr );

        }

 

        return*this;

}

 

 

16CheckoutRecord类还应该定义其他赋值操作符吗?如果是,解释哪些类型应该用作操作数并解释为什么。为这些类型实现赋值操作符。

从应用角度考虑,可能会修改预约时间date_due,可通过设置新的赋值操作符来实现;或者是往wait_list里添加排队读者,也可以通过设置新的赋值操作符来实现。

// set new date_due

CheckoutRecord&CheckoutRecord::operator=( const& new_due )

{

      date_due = new_due;

      return *this;

}

// add new readerswho wait for some books

CheckoutRecord&CheckoutRecord::operator=( const std::pair<string,string>& new_waiter)

{

      pair<string,string> *ppr = newpair<string, string>;

      *ppr = new_waiter;

      wait_list.push_back( ppr );

      return *this;

}

1714.2.1节习题中定义了一个CheckoutRecord类,为该类定义一个下标操作符,从等待列表中返回一个名字。

下标重载:

pair<string,string>& CheckoutRecord::operator[ ]

(const vector< pair<string, string>* >::size_type index )

{

        return*wait_list.at(index );

}

 //下标操作符重载

constpair<string, string>&CheckoutRecord::operator[]

(const vector< pair<string, string>* >::size_type index ) const

{

        return*wait_list.at(index );

}

 

18。讨论用下标操作符实现这个操作的优缺点。

优点:使用简单。

缺点:操作的语义不够清楚,因为CheckoutRecord不是一个通常意义上的容器,而且等待者也不是CheckoutRecord容器中的一个元素,不易使人弄明白怎样用。

 

19。提出另一种方法定义这个操作。

可以将这个操作定义成普通的函数, pair<string, string>& get_a_waiter(const size_t index ) const pair<string, string>&get_a_waiter ( const size_t index ) const.

 

 

20。在ScreenPtr类的概略定义中,声明但没有定义赋值操作符,请实现ScreenPtr赋值操作符。

ScreenPtr&operator=( const ScreenPtr& sp )

{

      ++sp.ptr->use;

      if ( --ptr->use == 0 )

             delete ptr;

      ptr = sp.ptr;

      return *this;

}

 

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

class NoName

{

public:

      NoName( *p ): ps( new ScreenPtr(p) ) { }

      ScreenPtr operator->( )

      {

             return  *ps;

      }

      const ScreenPtr operator->( ) const

      {

             return  *ps;

      }

 

      ~NoName()

      {

             delete ps;

      }

 

private:

      ScreenPtr *ps;

};

 

22。智能指针可能应该定义相等操作符和不等操作符,以便测试两个指针是否相等或不等。将这些操作加入到ScreenPtr类。

class ScreenPtr

{

public:

      // …

       friend inline bool operator==( const ScreenPtr&, const ScreenPtr &);

       friend inline bool operator!=( const ScreenPtr&, const ScreenPtr &);

private:

      ScrPtr *ptr;

};

// operator ==

inline booloperator==( const ScreenPtr &p1, const ScreenPtr &p2 )

{

      return p1.ptr == p2.ptr;

}

      

// operator !=

inline booloperator!=( const ScreenPtr &p1, const ScreenPtr &p2 )

{

      return !( p1.ptr == p2-.ptr );

}

 

23CheckedPtr类表示指向数组的指针。为该类重载下标操作符和解引用操作符。使操作符确保CheckedPtr有效:它应该不可能对超出数组末端的元素进行解引用或索引。

//下标操作符重载

int&CheckedPtr::operator[]( const size_t index )

{

        if ( beg + index >= end )

                  throw out_ot_range( “ invalidindex“ );

        return *( beg + index );
}

 

const int& CheckedPtr::operator[] ( const size_t index ) const

{

        if ( beg + index >= end )

                  throw out_ot_range( “ invalidindex“ );

        return *( beg + index );

}

//解引用操作符重载

intCheckedPtr::operator*()

{

      if ( curr == end )

             throw out_of_range( “ invalidcurrent pointer” );

      return *curr;

}

const int&CheckedPtr::operator*() const

{

      if ( curr == end )

             throw out_of_range(“ invalidcurrent pointer”);

      return *curr;

}

 

24。习题14.23中定义的解引用操作符或下标操作符,是否也应该检查对数组起点之前的元素进行的解引用或索引?解释你的答案。

对于下标操作符,应该进行检查,因为当用户给出的下标索引值小于0时,编译器不会出现编译错误,而会出现运行时错误。应修改为:

//下标操作符重载

int&CheckedPtr::operator[]( const size_t index )

{

        if ( beg + index >= end || beg +index < beg )

                  throw out_ot_range( “ invalidindex“ );

        return *( beg + index );
}

 

const int& CheckedPtr::operator[] ( const size_t index ) const

{

        if ( beg + index >= end || beg +index < beg )

                  throw out_ot_range( “ invalidindex“ );

        return *( beg + index );

}

而对于解引用操作符,返回curr所指向的数组元素,在创建对象时已经将curr初始化为指向数组的第一个元素,只有当执行操作时才会对curr进行减的操作,而操作符已经对curr的值与数组起点进行了检查,所以不用再在这里检查。

 

25。为了表现得像数组指针,CheckedPtr类应实现相等和关系操作符,以便确定两个CheckedPtr对象是否相等,或者一个小于另一个,诸如此类。为CheckedPtr类增加这些操作。

应将这些操作符声明为CheckedPtr的友元。

//相等操作符

bool operator==(const CheckedPtr& lhs, const CheckedPtr& rhs )

{

      return lhs.beg == rhs.beg &&lhs.end == rhs.end && lhs.curr == rhs.curr;

}

bool operator!=(const CheckedPtr & lhs, const CheckedPtr& rhs )

{

      return !( lhs == rhs );

}

 

//关系操作符

bool operator<(const CheckedPtr & lhs, const CheckedPtr& rhs )

{

      return lhs.beg == rhs.beg &&lhs.end == rhs.end

                    && lhs.curr <rhs.curr;

}

bool operator>(const CheckedPtr & lhs, const CheckedPtr& rhs )

{

      return lhs.beg == rhs.beg &&lhs.end == rhs.end

                    && lhs.curr >rhs.curr;

}

bool operator<=(const CheckedPtr & lhs, const CheckedPtr& rhs )

{

      return !( lhs.curr > rhs.curr );

}

bool operator >=(const CheckedPtr & lhs, const CheckedPtr& rhs )

{

      return !( lhs.curr < rhs.curr );

}

 

 

26。为CheckedPtr类定义加法或减法,以便这些操作符实现指针运算。

将这两个操作符声明为类的友元。

CheckedPtr operator+(const CheckedPtr& lhs, const size_t n )

{

      CheckedPtr temp( lhs );

      temp.curr += n;

      if ( temp.curr > temp.end )

             throw out_of_range(“ Too large n,over.”);

      return temp;

}

CheckedPtr operator-(const CheckedPtr& lhs, const size_t n )

{

      CheckedPtr temp( lhs );

      temp.curr -= n;

      if ( temp.curr < temp.beg )

             throw out_of_range(“ Too large n,over.”);

      return temp;

}

用到了复制构造函数,定义为:

CheckedPtr::CheckedPtr(const CheckedPtr& cp ):

beg( cp.beg ), end(cp.end ), curr( cp.curr )

{ }

 

27。讨论允许将空数组实参传给CheckedPtr构造函数的优缺点。

优点:构造函数的定义简单。缺点:导致构造的对象没有指向有效的数组,从而失去使用价值。应该在构造函数里控制参数确保beg<end.

 

28。没有定义自增和自减操作符的const版本,为什么?

const所修饰的operator,不可以改变对象,而自增和自减肯定改变了对象,与const意义相反,所以不定义const版本。

 

29。我们也没有实现箭头操作符,为什么?

因为此类所指向的是int型数组,int型为内置类型,而箭头操作符必须返回一个类类型的指针,所以不实现。

 

30。定义一个CheckedPtr版本,保存Screen数组。为该类实现重载的自增、自减。解引用和箭头等操作符。

class CheckedPtr

{

public:

      CheckedPtr( Screen *b, Screen *e ): beg(b ), end( e ), curr( b ) { }

      

      // 自增、自减

      CheckPtr& operator++();

      CheckPtr& operator—();

      CheckPtr& operator++( int );

      CheckPtr& operator—( int );

 

      // 箭头操作符

      Screen* operator->();

      const Screen* operator->() const;

      

      // 解引用操作

      Screen& operator*();

      const Screen& operator*();

private:

      Screen *beg;

      Screen *end;

      Screen *curr;

};

 

CheckPtr&CheckPtr::operator++()

{

      if ( curr == end )

             throw out_of_range( “incrementpast the end of CheckedPtr”);

      ++curr;

      return *this;

}

CheckPtr&CheckPtr::operator—()

{

      if ( curr == begin )

             throw out_of_range( “decrementpast the beginning of CheckedPtr”);

      --curr;

      return *this;

}

//后缀式

CheckPtr&CheckPtr::operator++( int )

{

      CheckedPtr temp( *this );

      ++*this;

      return temp;

}

CheckPtr&CheckPtr::operator—( int )

{

      CheckedPtr temp( *this );

      --*this;

      return temp;

}

//箭头操作符

Screen*CheckedPtr::operator->()

{

      return curr;

}

const Screen*CheckedPtr::operator->() const

{

      return curr;

}

 

Screen&CheckedPtr::operator*()

{

      if ( curr == end )

             throw out_of_range( “invalidcurrent pointer.”);

      return *curr;

}

const Screen&CheckedPtr::operator*() const

{

      if ( curr == end )

             throw out_of_range( “invalidcurrent pointer.”);

      return *curr;

}

 

31。定义一个函数对象执行“如果……则……否则”操作;该函数对象应接受三个形参;它应该测试第一个形参;如果测试成功,则返回第二个形参;否则,返回第三个形参。

class NoName

{

public:

      NoName() { }

      NoName( int i1, int i2, int i3 ): iVal1(i1 ), iVal2( i2 ), iVal3( i3) { }

      int operator() ( int i1, int i2, int i3 )

      {

             return i1? i2: i3;

      }

private:

      int iVal1;

      int iVal2;

      int iVal3;

};

 

32。一个重载的函数调用操作符可以接受多少个操作数?

0个或多个。

 

33。使用标准库算法和GT_cls类,编写一个程序查找序列中第一个比指定值大的元素。

//14.33_Gt_cls_and_algorithm.cpp :定义控制台应用程序的入口点。

//

 

#include"stdafx.h"

#include<iostream>

#include<string>

#include<vector>

#include<algorithm>

usingnamespace std;

 

classGT_cls

{

public:

        GT_cls(conststring  gW =" " ) : givenWord(gW ) { }

 

        bool operator() (const string &s )

        {

                  return( s >givenWord);

        }

 

private:

        std::stringgivenWord;

};

 

int_tmain(int argc, _TCHAR* argv[])

{

        std::cout <<"Input some words( ctrl + z to end ):" << std::endl;

        vector<string>text;

        stringword;

        while (std::cin>>word )

        {

                  text.push_back(word );

        }  // end of input the text

 

        // input thegiven word

        std::cin.clear();

        std::cout <<" Then, input one given word:\t";

        stringgWord;

        std::cin >>gWord;

 

        //      deal with text , to realize find the first word which is bigger than the givenword

        vector<string>::iteratorit =find_if(text.begin(),text.end(),GT_cls( gWord ));

        if  ( it != text.end() )

                  std::cout <<"\nThen the first word in the text you input," <<std::endl

                                                       <<" \twhich is bigger than the given wordis:" <<std::endl

                                                       <<"\t" <<  *it <<std::endl;

 

        system("pause");

        return0;

}

 

 

34。编写类似于GT_cls的类,但测试两个值是否相等。使用该对象和标准库算法编写程序,替换序列中给定值的所有实例。

//14.34_GT_cls.cpp :定义控制台应用程序的入口点。

 

#include"stdafx.h"

#include<iostream>

#include<string>

#include<vector>

#include<algorithm>

usingnamespace std;

 

classGT_cls

{

public:

        GT_cls(intiVal = 0 ): val(iVal ){   }

 

        bool operator() (const int & iv )

        {

                  return( iv ==val);

        }

 

private:

        int val;

};

 

int_tmain(int argc, _TCHAR* argv[])

{

        std::cout <<"Input some nums( ctrl + z to end ):" << std::endl;

        vector<int>iVec;

        int iVal;

        while (std::cin>>iVal)

        {

                  iVec.push_back(iVal );

        }  // end of input the iVec

 

        cin.clear();

 

        cout<< " Input a num which will be replaced:\t";

        int rp;

        cin>> rp;

 

        cout<< " Input a given num to insert:\t";

        int givenNum;

        cin>> givenNum;

        

        // replace

        replace_if(iVec.begin(),iVec.end(),GT_cls( rp ), givenNum );

        cout<< " Now , the new vector<int>iVec, is : \n\t";

        for ( vector<int>::iteratorit = iVec.begin();it != iVec.end(); ++it )

        {

                  cout<< *it <<"";

        }

 

        system("pause");

        return0;

}

35。编写类似于GT_cls的类,但测试给定string对象的长度是否与其边界相匹配。报告输入中有多少单词的长度在110之间。

//14.35_BT_cls.cpp :定义控制台应用程序的入口点。

//

 

#include"stdafx.h"

#include<iostream>

#include<string>

#include<vector>

#include<algorithm>

usingnamespace std;

 

classBT_cls

{

public:

        BT_cls(size_t len1 = 0, size_t len2 =0  )

        {

                  if( len1 <len2)

                  {

                           minlen = len1;

                           maxlen = len2;

                  }

                  else

                  {

                           minlen = len2;

                           maxlen = len1;

                  }

        }

 

        bool operator() (const string &s )

        {

                  return( s.size()>=minlen && s.size() <=maxlen );

        }

 

private:

        std::string::size_typeminlen, maxlen;

};

boolisShorter( conststring &s1, const string &s2 )

{

         return s1.size() < s2.size();

}

 

 

int_tmain(int argc, _TCHAR* argv[])

{

        std::cout <<"Input some words( ctrl + z to end ):" << std::endl;

        vector<string>text;

        stringword;

        while (std::cin>>word )

        {

                  text.push_back(word );

        }  // end of input the text

 

        //      deal with text 

        sort( text.begin(),text.end() );                 

        text.erase(unique( text.begin(),text.end() ), text.end() );

        stable_sort(text.begin(),text.end(),isShorter );

 

        // to counthow many words' length are between 1-10

        vector<string>::size_typecnt =count_if(text.begin(),text.end(),BT_cls( 1, 10 ));

        std::cout << " There are " <<cnt << "words' length is between 1-10." <<std::endl;

 

        system("pause");

        return0;

}

 

 

 

 

36。修改前一段程序以报告在19之间以及10以上的单词的数目。

// 14.36_BT_cls_Words.cpp:定义控制台应用程序的入口点。

//

#include"stdafx.h"

#include<iostream>

#include<string>

#include<vector>

#include<algorithm>

usingnamespace std;

 

classBT_cls

{

public:

        BT_cls(size_t len1 = 0, size_t len2 =0  ) : minlen(len1 ), maxlen(len2 ) { }

 

        bool operator() (const string &s )

        {

                  return( s.size()>=minlen && s.size() <=maxlen );

        }

 

private:

        std::string::size_typeminlen, maxlen;

};

 

int_tmain(int argc, _TCHAR* argv[])

{

        std::cout <<"Input some words( ctrl + z to end ):" << std::endl;

        vector<string>text;

        stringword;

        while (std::cin>>word )

        {

                  text.push_back(word );

        }  // end of input the text

 

        std::cin.clear();

 

        //      deal with text , to count how many words' length are between 1-9

        size_tcnt =count_if(text.begin(),text.end(),BT_cls( 1, 9 )) ;

        std::cout <<"\nThereare "<< cnt <<" words' length are 1-9." << std::endl;

        cout<< " And there are " <<text.size() -cnt <<"words' length is 10 or more." << endl;

 

 

        system("pause");

        return0;

}

37。使用标准库函数对象和函数适配器,定义一个对象用于:

(a)查找大于1024的所有值。

(b)查找不等于pooh的所有字符串。

(c)将所有值乘以2

(a) find_if(vec.begin(), vec.end(), bind2nd( greater<int>(), 1024 ) );

(b) find_if (svec.begin(), svec.end(), bind2nd( not_equal_to<string>(), “pooh”);

(c) transform(ivec.begin(), ivec.end(), ivec.begin(), bind2nd( multiplies<int>(), 2 ));

 

 

 

38。最后一个count_if调用中,用not1bind2dn(less_equal<int>(),10 ) 的结果求反。为什么使用not1而不用not2?

not1用于将一元函数对象的真值求反,not2用于将二元函数对象的真值求反,函数适配器bind2ndless_equal<int>对象的右操作数绑定到10,从而less_equal对象由二元函数对象转换为一元函数对象,所以用not1求反。

 

 

39。使用标准库函数对象代替GT_cls来查找指定长度的单词。

 

输入一个指定长度:

vector<string>text;

// …  // input words into text

string::size_typelen;

cin >> len;

string *w;

for (vector<string>::iterator it = text.begin(); it != text.end(); ++it )

{

      w = find_if ( it, text.end(), bind2nd(equal_to<string::size_type>(), len) );
}

cout << “ Thewords whose length is “<< len << ” was found.Itis

      << *w <<endl;

 

 

40。编写可将Sales_item对象转换为string类型和double类型的操作符。你认为这些操作符应返回什么值?你认为定义这些操作符是个好办法吗?解释你的结论。

Sales_item::operatorstring() const

{

      return isbn;

}

Sales_item::operatordouble() const

{

      return revenue;

}

不是好办法,因为不必在需要stirng类型和double类型对象的地方使用Sales_item对象,这种做法没有太大用处。

 

41。解释这两个转换操作符之间的不同:

class Integral

{

public:

      operatorconst int();

      operatorint() const;

};

不同:前者将对象转换为const int值,后者将对象转换为int值,前者太严格,限制使用在可以使用const int 值的地方,只保留后者,将变得更为通用。

 

42。为14.2.1节习题中的CheckoutRecord类定义到bool的转换操作符。

CheckoutRecord::operatorbool() const

{

   return wair_list.empty();

}

 

43。解释bool转换操作符做了什么。这是这个CheckoutRecord类型转换唯一可能的含义吗?解释你是否认为这个转换是一种转换操作的良好使用。

wait_list为空的CheckoutRecord对象转换为bool类型的true,将不为空的对象转换为false.

不是唯一的含义,还可以将bool转换符定义为当前日期是否已经超过date_due,即判断某本借出的书是否已经过期。

上述定义可用于判断是否有读者在等待借阅,当某本书被归还时,可以用相应的CheckoutRecord对象作为判断条件以确定是否通知该书的等待着。因此这个转换是一种转换操作的良好使用。

 

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

class LongDouble

{

public:

      operatordouble();

      operatorfloat();

};

LongDouble ldObj;

(a) int ex1 = ldObj; (b) float ex2 = ldObj;

(a)既可以先使用从Longdoubledouble的转换操作,再是偶那个从doubleint的标准转换,也可以使用从LongDoublefloat的转换操作,再使用从floatint的标准转换,二者没有优劣之分,具有二义性。

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

 

 

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

class LongDouble

{

public:

      LongDouble(double );

      //…

};

void calc( int );

void calc( LongDouble );

double dval;

calc( dval ); // which function?

最佳可行函数是void calc(int), 调用此函数的转换为:将实参double类型转换为int类型的,为标准转换;调用void calc( LongDouble)函数时,将实参从double转换为LongDouble类型,为类类型转换,因为标准转换优于类类型转换,所以第一个函数为最佳可行函数。

 

46。对于main中的加操作,哪个operator是最佳可行函数?列出候选函数。可行函数以及对每个可行函数中实参的类型转换。

class Complex

{

public:

      Complex(double );

      //…

};

class LongDouble

{

      friendLongDouble operator+( LongDouble, int );

public:

      LongDouble(int );

      operatordouble();

      LongDoubleoperator+( const Complex & );

      //…

};

LongDouble operator+( const LongDouble&, double);

LongDouble ld( 16.08 );

double res = ld + 15.05; // whichoperator+?

(a)内置类型的+操作符

      ldLongDouble转换为double类型。

(b)友元friend LongDouble operator+( LongDouble, int );

       15.05double类型转换为int类型(使用标准转换)。

(c) LongDoubleoperator+( const Complex & );

      15.05转换为Complex型,使用Complex类的构造函数。

(d)全局函数LongDoubleoperator+( const LongDouble &, double);

      无需进行类型转换,因此虽然这4个都为候选函数,和可行函数,但是这个是最佳可行函数。

0 0