日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ primer 14章习题答案

發(fā)布時(shí)間:2024/4/18 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ primer 14章习题答案 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

14.1節(jié)

練習(xí)14.1

相同點(diǎn):對于優(yōu)先級和結(jié)合型以及操作數(shù)的數(shù)目都不變。

不同點(diǎn):重載操作符必須具有至少一個(gè)class或枚舉類型的操作數(shù)。

14.2

下面所有的代碼行可能把好幾個(gè)文件放在一起了。

//sales_data.h#ifndef SALES_DATA_H #define SALES_DATA_H #include <string> #include <iostream> using namespace std; class Sales_data {friend void print(ostream &os,Sales_data rhs);friend istream& operator>>(istream &,Sales_data &rhs);friend ostream& operator<<(ostream &,const Sales_data &rhs);public:Sales_data() = default;Sales_data(const string &s):bookno(s){}Sales_data(const string &s,unsigned n,double r):bookno(s),cnt(n),revenue(r){}Sales_data(istream &is);const string & isbn()const{return bookno;} Sales_data operator+(const Sales_data &rhs);Sales_data &operator+=(const Sales_data &rhs);private:unsigned cnt = 0;double revenue = 0.0;string bookno; }; void print(ostream &os,Sales_data rhs); istream& operator>>(istream &,const Sales_data &rhs); ostream& operator<<(ostream &,const Sales_data &rhs); #endif//functions.cc #include <string> #include <iostream> #include "sales_data.h" using namespace std;Sales_data & Sales_data::operator+=(const Sales_data &rhs) { if(this->bookno != rhs.bookno)throw runtime_error("Not same type."); this->revenue += rhs.revenue; this->cnt += rhs.cnt;return *this; } Sales_data Sales_data::operator+(const Sales_data &rhs) { if(this->bookno != rhs.bookno)throw runtime_error("Not the same type."); Sales_data data; data.bookno = rhs.bookno; data.revenue = this->revenue + rhs.revenue; data.cnt = this->cnt + rhs.cnt;return data; } void print(ostream &os,Sales_data rhs) { os <<"bookno:"<<rhs.bookno << endl; os << "\trevenue:" << rhs.revenue << endl; os << "\tcnt:" << rhs.cnt << endl; }istream& operator>>(istream &is,Sales_data &rhs) { is >> rhs.bookno >> rhs.cnt >> rhs.revenue; return is; } ostream& operator<<(ostream &os,const Sales_data &rhs) { os << rhs.bookno << rhs.cnt << rhs.revenue; return os; }//main.cc #include <string> #include <iostream> #include "sales_data.h" using namespace std; int main() { Sales_data s1("book1",12,120); Sales_data s2("book1",12,130); s1 += s2; Sales_data s3 = s1 + s2; print(cout,s1); print(cout,s3); cout << "輸入s1:" << endl; cin >> s1; cout << s1 << endl;return 0; } bookno:book1revenue:250cnt:24 bookno:book1revenue:380cnt:36 輸入s1: isbnabcdefg 12 120 isbnabcdefg12120

14.2

(a) 應(yīng)用了c++內(nèi)置版本的==,比較兩個(gè)指針。

(b)應(yīng)用了svec1[1] == svec2[0] 應(yīng)用了string版本的重載==。

(c)應(yīng)用了svec1 == svec2 應(yīng)用了vector版本的重載==。

(d)svec1[0] == "stone"應(yīng)用了 string版本的重載==,字符串字面知被轉(zhuǎn)換為string。

14.3
答:

(a)%通常定義飛成員

(b)%=通常定義為成員,因?yàn)闀?huì)改變對象的狀態(tài)

(c)++通常定義為類成員,因?yàn)樗鼤?huì)改變對象的狀態(tài)。

(d)->必須定義為成員否則,否則編譯器會(huì)報(bào)錯(cuò)。
(e)<<通常定義非成員。因?yàn)樽霾僮鲾?shù)為輸出流,如果定義成成員,那就不符合<<的本來內(nèi)置習(xí)慣。

(f)&&通常是定義成非成員

(g)==通常定義為非成員(操作符具有對稱性一般定義為非成員,這樣才可以必要時(shí)候轉(zhuǎn)換,成員不能轉(zhuǎn)換,左邊操作數(shù)是確定的)

(h)()必須定義為成員,否則編譯器會(huì)報(bào)錯(cuò)。

總結(jié):

賦值=、下標(biāo)[]、成員->、成員()這四個(gè)是必須定義成成員函數(shù)的。

復(fù)合的運(yùn)算符一般定義成成員,但是不是必須。

改變對象狀態(tài)的運(yùn)算符(++,--)或者和對象有密切關(guān)系的運(yùn)算符應(yīng)該定義成成員函數(shù),例如遞增遞減和解引用。

具有對稱運(yùn)算的運(yùn)算符可能轉(zhuǎn)換任意一端的運(yùn)算對象,例如算數(shù)、關(guān)系、相等性和位運(yùn)算符要定義成非成員運(yùn)算符。

14.7

類內(nèi)聲明

friend ostream & operator<<(ostream & ,const String &rhs);

類外聲明:

ostream & operator<<(ostream & ,const String &rhs);

最后源文件中定義:

ostream & operator<<(ostream &os,const String &rhs) { for(auto p = rhs.elements; p != rhs.first_free; ++p){os << *p; }return os; }

補(bǔ)充和理解:

這里定義==和!=一定注意,如果類中有唯一一個(gè)動(dòng)態(tài)內(nèi)存,比如說strblobptr,當(dāng)wptr都非空時(shí)候才比較curr,如果wptr都空時(shí)不必比較curr。也就是含有動(dòng)態(tài)內(nèi)存的類,比較的時(shí)候可能變量要分級對待(分級是我自己發(fā)明的說話,也就是說當(dāng)內(nèi)存都是nullptr時(shí)候,不必比較其它變量,也就是變量中間有級別的有限性,某些情況下,某個(gè)或者某些變量不必參與比較)。

14.2.2

14.3

14.3.1練習(xí)答案,這個(gè)答案產(chǎn)生一個(gè)疑問?兩個(gè)StrBlob相等,到底是應(yīng)該是data內(nèi)的內(nèi)容相等?還是data應(yīng)該指向同一個(gè)vector?答案是比較了StrBlob的data的

bool operator==(const StrBlob & lhs,const StrBlob &rhs) {return (*(lhs.data) == *(rhs.data)); }

14.3.2節(jié)練習(xí)

14.18

friend聲明和函數(shù)原型聲明就略去了。看下面的定義:

//strblob.h中的bool operator==(const StrBlob &lhs,const StrBlob & rhs) {return lhs.data == rhs.data; } bool operator<(const StrBlob &lhs,const StrBlob &rhs) {return *(lhs.data) < *(rhs.data);} bool operator>(const StrBlob &lhs,const StrBlob &rhs) {return *(lhs.data) > *(rhs.data);}bool operator<=(const StrBlob &lhs,const StrBlob &rhs) { return *(lhs.data) <= *(rhs.data);} bool operator>=(const StrBlob &lhs,const StrBlob &rhs) { return *(lhs.data) >=*(rhs.data);}

說明:就是比較兩個(gè)strblob對象是否指向同一個(gè)data,如果是則正確,如果否,那么不想等。

(1)這里是lhs.data如果和rhs.data相等的時(shí)候,那么 strblob對象相等,也就是data必須是同一個(gè)shared_ptr,也就是說data必須是指向同一個(gè)對象的兩個(gè)對象才能相等。這里不是通常內(nèi)容代數(shù)上相等的含義,通常代數(shù)上相等的含義,比如:

(2)如果==和!=已經(jīng)定義了一個(gè),那么另一個(gè)用這個(gè)來定義。性能沒有提高,但是代碼的利用率提高了。

vector<int> v1{1,2,3,4},v2{1,2,3,4};

而是,兩個(gè)data的值是否相等。

strblobptr類:

bool operator== (const StrBlobPtr &lhs,const StrBlobPtr &rhs) { if(lhs.wptr.lock() == rhs.wptr.lock()){//在某個(gè)條件成立時(shí)候返回真//在這個(gè)條件不成立時(shí),才求另一個(gè)條件的值(用 || )return !lhs.wptr.lock() || lhs.curr == rhs.curr;} else{return false; }} bool operator!= (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return !(lhs == rhs); }bool operator> (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) > *(rhs.wptr.lock()); } bool operator< (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) < *(rhs.wptr.lock()); } bool operator>= (const StrBlobPtr&,const StrBlobPtr&) {return *(lhs.wptr.lock()) >= *(rhs.wptr.lock()); } bool operator<= (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) <= *(rhs.wptr.lock()); }

這里含有動(dòng)態(tài)內(nèi)存,動(dòng)態(tài)內(nèi)存wptr和變量,如果在動(dòng)態(tài)內(nèi)存wptr為空的時(shí)候(兩個(gè)動(dòng)態(tài)內(nèi)存相等的情況下),比較curr的大小是無意義的。所以這里wptr和curr不是同一個(gè)級別的變量。作用的大小也是不對等的。

注意:這里判斷兩個(gè)對象相等的時(shí)候,當(dāng)

(1)兩個(gè)對象的wptr指針都為空

(2)兩個(gè)對象指向的對象相同且非空,且curr相等時(shí)。

這個(gè)問題存在這樣一個(gè)現(xiàn)象,當(dāng)兩個(gè)wptr都為空時(shí)候,不用求解curr值(對象相等或者不想等和curr沒有關(guān)系)。

那么這個(gè)時(shí)候,正好可以用關(guān)系運(yùn)算符 ||的短路求值特性去寫代碼。(!wptr.lock() || lhs.curr == rhs.curr)。

同時(shí),strblobptr對象的==定義和strblob對象的==的定義是邏輯上等價(jià)的,都是必須指針指向同一個(gè)對象才得到兩個(gè)對象相等(而不是兩個(gè)對象的內(nèi)容完全相等)。

string.h

bool operator==(const String &lhs,const String &rhs) { if(lhs.size() != rhs.size())return false;for(auto ptr1 = lhs.begin(),ptr2 = rhs.begin();ptr1 != lhs.end() && ptr2 != rhs.end(); ++ ptr1,++ptr2){if(*ptr1 != *ptr2)return false; } return true; } bool operator!=(const String &lhs,const String &rhs) {return !(lhs == rhs); }//下面這段代碼是可以簡化的,可以簡化為: /******************************************************************************* bool operator>(const String &lhs,const String &rhs) {return strcmp(lhs.str,rhs.str) > 0; } ********************************************************************************/ bool operator>(const String &lhs,const String &rhs) { auto p1 = lhs.begin(),p2 = rhs.begin(); for(;p1 != lhs.end() && p2 != rhs.end(); ++ p1,++ p2){if(*p1 > *p2)return true;else if(*p1 < *p2)return false;} if(p1 == lhs.end())return false;return true; }下面這個(gè)函數(shù)也可以簡化為下面的形式: /******************************************************************************* bool operator<(const String &lhs,const String &rhs) {return strcmp(lhs.str,rhs.str) < 0; } ********************************************************************************/bool operator<(const String &lhs,const String &rhs) { auto p1 = lhs.begin(),p2 = rhs.begin(); for(;p1 != lhs.end() && p2 != rhs.end();++ p1,++ p2){if(*p1 < *p2)return true;else if(*p1 > *p2)return false; } if(p2 == rhs.end())return false; return true; } bool operator>=(const String &lhs,const String &rhs) { return !(lhs < rhs);} bool operator<=(const String &lhs,const String &rhs) {return !(lhs > rhs); }

上面的每個(gè)函數(shù)都可以利用strcmp() >0 或者 strcmp() < 0?? 或者 strcmp() == 0 來簡化原來的函數(shù)。

strvec.h

bool operator==(const StrVec &lhs,const StrVec &rhs) { if(lhs.size() != rhs.size())return false; for(auto ptr1 = lhs.begin(),ptr2 = rhs.begin();ptr1 != lhs.end() && ptr2 != rhs.end(); ++ ptr1,++ ptr2){if(*ptr1 != *ptr2)return false;} return true; } bool operator!=(const StrVec &lhs,const StrVec &rhs) {return !(lhs == rhs); } bool operator>=(const StrVec &lhs,const StrVec &rhs) { for(auto ptr1 = lhs.begin(),ptr2 = rhs.begin(); ptr1 != lhs.end(),ptr2 != rhs.end(); ++ ptr1,++ ptr2){if(*ptr1 > *ptr2)return true;else if(*ptr1 < *ptr2)return false;} if(lhs.size() >= lhs.size()) //or can:if(ptr2 == rhs.end()) return true;return false;return true; elsereturn false; } bool operator<=(const StrVec &lhs,const StrVec &rhs) { auto p1 = lhs.begin(),p2 = rhs.begin(); for( ;p1 != lhs.end(),p2 != rhs.end(); ++ p1,++ p2){if(*p1 < *p2)return true; else if(*p1 > *p2)return false; } //到這里說明前面所有部分相等 if(p1 == lhs.end())return true; return false; } bool operator>(const StrVec &lhs,const StrVec &rhs) {return !(lhs <= rhs); }bool operator<(const StrVec &lhs,const StrVec &rhs) { return !(lhs >= rhs); }

strvec比較==邏輯規(guī)則:

首先當(dāng)size()不等的時(shí)候,馬上得到不想等。?

逐個(gè)比較兩個(gè)對象的數(shù)據(jù),如果出現(xiàn)不想等的對象,那么返回false

返回true.

這個(gè)算法其實(shí)是把比較的結(jié)果分成了3種情況。

strblob和strblobptr對象:

bool operator==(const StrBlob &lhs,const StrBlob & rhs) {return lhs.data == rhs.data; } bool operator<(const StrBlob &lhs,const StrBlob &rhs) {return *(lhs.data) < *(rhs.data);} bool operator>(const StrBlob &lhs,const StrBlob &rhs) {return *(lhs.data) > *(rhs.data); //這里兩個(gè)()不加也可以.比*要優(yōu)先 }bool operator<=(const StrBlob &lhs,const StrBlob &rhs) { return *(lhs.data) <= *(rhs.data);} bool operator>=(const StrBlob &lhs,const StrBlob &rhs) { return *(lhs.data) >=*(rhs.data);} bool operator== (const StrBlobPtr &lhs,const StrBlobPtr &rhs) { if(lhs.wptr.lock() == rhs.wptr.lock()){//在某個(gè)條件成立時(shí)候返回真//在這個(gè)條件不成立時(shí),才求另一個(gè)條件的值(用 || )return !lhs.wptr.lock() || lhs.curr == rhs.curr;} else{return false; }} bool operator!= (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return !(lhs == rhs); }bool operator> (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) > *(rhs.wptr.lock()); } bool operator< (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) < *(rhs.wptr.lock()); } bool operator>= (const StrBlobPtr&,const StrBlobPtr&) {return *(lhs.wptr.lock()) >= *(rhs.wptr.lock()); } bool operator<= (const StrBlobPtr &lhs,const StrBlobPtr &rhs) {return *(lhs.wptr.lock()) <= *(rhs.wptr.lock()); }

總結(jié):

一、定義==運(yùn)算和!=運(yùn)算注意:

(1)如果有動(dòng)態(tài)指針,比較智能指針的原則是兩個(gè)指針是否指向同一個(gè)對象。shared_ptr和weak_ptr都是如此。

? (2)如果一個(gè)對象有動(dòng)態(tài)內(nèi)存和其他數(shù)據(jù),可能需要分級對待。比較時(shí)候,首先看動(dòng)態(tài)內(nèi)存是否非空。

如果動(dòng)態(tài)內(nèi)存空,則不比較另外其他數(shù)據(jù)。

如果動(dòng)態(tài)內(nèi)存為空,則才需要比較其它數(shù)據(jù)。

(3)如果是allocator對象分配的內(nèi)存,那么逐個(gè)比較每個(gè)數(shù)據(jù)即可。

二、定義>、<、>=、 <=時(shí)候得到的結(jié)論:

(1)答案中是利用strcmp(lhs.str,rhs.str),來比較的。但是自己在g++編譯器中,編譯器提示string對象沒有str成員。所以,自己改成了利用c_str()成員函數(shù):

strcmp(lhs.c_str(),rhs.c_str())

來比較,==得到結(jié)果0,大于得到結(jié)果正數(shù),小于得到結(jié)果負(fù)數(shù)。

(2)兩個(gè)strblob對象比較是否相等時(shí)候,是比較兩個(gè)data是否相等(指針本身是否相等)。而>、<、>=、<=四個(gè)運(yùn)算符是指的兩個(gè)字符串的大小關(guān)系。也就是兩個(gè)vector的大小關(guān)系。

(3)比較兩個(gè)strblobptr時(shí)候,兩個(gè)對象wptr必須指向同一個(gè)vector,否則沒有比較的意義,具體看答案如下:

(3)

14.4節(jié)練習(xí)

14.20

關(guān)于這些函數(shù)的友元聲明和原型聲明就省略了。

Sales_data operator+(const Sales_data &lhs ,const Sales_data &rhs) { auto data = lhs; data += rhs; return data; } Sales_data operator-(const Sales_data &lhs,const Sales_data &rhs) { auto data = lhs; data.revenue -= rhs.revenue; data.cnt -= rhs.cnt;return data; }

14.21

我自己覺得應(yīng)該如下書寫:

Sales_data operator+(const Sales_data &lhs ,const Sales_data &rhs) { auto data = lhs; data.revenue += rhs.revenue; data.cnt += rhs.cnt; return data; } Sales_data & Sales_data::operator+=(const Sales_data &rhs) {*this = *this + rhs;return *this; }

由此可見,上面的書寫方式,性能上沒有任何優(yōu)勢,但是代碼難閱讀。

我找到了這個(gè)題答案書上寫的答案:

?在operator+=函數(shù)中,顯然返回值是Sales_data &,但是這里卻沒有用return語句返回一個(gè)值,顯然錯(cuò)誤。即使我們知道*this = (*this) + rhs,其實(shí)已經(jīng)可以改變左側(cè)運(yùn)算對象,但是仍然需要一個(gè)返回值的。

14.22

Sales_data& Sales_data::operator=(const Sales_data &rhs) {bookno = rhs.bookno;revenue = rhs.revenue;cnt = rhs.cnt;return *this; } Sales_data &Sales_data::operator=(const string & s) {bookno = s;revenue = 0;cnt = 0;return *this; }

有第二個(gè)賦值運(yùn)算符,就可以把string對象(或者能轉(zhuǎn)化為string的字符串字面值)賦值給sales_data對象了。

14.23

類內(nèi)聲明省去了

StrVec::StrVec(initializer_list<string> li) { auto data = allocate_n_copy(li.begin(),li.end()); elements = data.first; first_free = cap = data.second; }

14.24

#include <string> #include <iostream> #include "date.h" using namespace std; int main() {return 0; } #include <string> #include <iostream> #include "date.h" using namespace std; ostream &operator <<(ostream &os,const Date &dt) { const char sep = '\t'; os << "year:" << dt.year << sep << "month:" << dt.month << sep << "day:" << dt.day <<endl;return os; }Date::Date() = default;istream & operator>>(istream &is,Date &dt) { is >> dt.year >> dt.month >> dt.day; if(!is){dt = Date();}return is;}bool operator==(const Date &lhs,const Date &rhs) {return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day; }bool operator!=(const Date &lhs,const Date &rhs) {return !(lhs == rhs); } #include <string> #include <iostream> using namespace std; class Date; class Date {friend ostream &operator <<(ostream &os,const Date &dt);friend istream &operator >>(istream &is,Date &dt);friend bool operator==(const Date &lhs,const Date &rhs);friend bool operator!=(const Date &lhs,const Date &rhs);public:Date();Date(int y,int m,int d){year = y ;month = m;day = d;}private:int year;int month;int day; }; ostream &operator <<(ostream &os,const Date &dt); istream &operator >>(istream &is,Date &dt); bool operator==(const Date &lhs,const Date &rhs); bool operator!=(const Date &lhs,const Date &rhs);

?14.5節(jié)

習(xí)題14.26

Date & Date::operator=(const string &date) { istringstream is(date); char ch1,ch2; is >> year >> ch1 >> month >> ch2 >> day; if(!is || ch1 != '-' || ch2 != '-' )throw invalid_argument("Bad date"); if(month < 1 || month > 12 || day < 1 || day > 21)throw invalid_argument("Bad date"); return *this; }

?

string &StrBlob::operator[](size_t n) {return (*data)[n];} const string &StrBlob::operator[](size_t n)const {return (*data)[n]; }string &StrBlobPtr::operator[](size_t n) { return (*wptr.lock())[n];} const string &StrBlobPtr::operator[](size_t n)const {return (*wptr.lock())[n]; }

總結(jié)

以上是生活随笔為你收集整理的C++ primer 14章习题答案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。