12。编写Sales_item操作符,用+进行实际加法,而+=调用+。与本节中操作符的实现方法相比较,讨论这个方法的缺点。
Sales_item Sales_item::operator+( const Sales_item& rhs ) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; }
将下面定义的非成员+=操作符声明为类Sales_item的友元: Sales_item operator+=( 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[]) { CheckoutRecord c1; cin >> c1; CheckoutRecord c2; c2 = c1; // 调用了类的赋值操作符= std::cout << c2 << std::endl; // 输出对象c2的内容 system(\); return 0; }
// 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
return *this;
16。CheckoutRecord类还应该定义其他赋值操作符吗?如果是,解释哪些类型应该用作操作数并解释为什么。为这些类型实现赋值操作符。
从应用角度考虑,可能会修改预约时间date_due,可通过设置新的赋值操作符来实现;或者是往wait_list里添加排队读者,也可以通过设置新的赋值操作符来实现。 // set new date_due
CheckoutRecord& CheckoutRecord::operator=( const& new_due ) { date_due = new_due; return *this;
}
// add new readers who wait for some books
CheckoutRecord& CheckoutRecord::operator=( const std::pair
17。14.2.1节习题中定义了一个CheckoutRecord类,为该类定义一个下标操作符,从等待列表中返回一个名字。 下标重载:
pair
( const vector< pair
// 下标操作符重载
const pair
( const vector< pair
18。讨论用下标操作符实现这个操作的优缺点。 优点:使用简单。
缺点:操作的语义不够清楚,因为CheckoutRecord不是一个通常意义上的容器,而且等待者也不是CheckoutRecord容器中的一个元素,不易使人弄明白怎样用。
19。提出另一种方法定义这个操作。
可以将这个操作定义成普通的函数, pair
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; };