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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符...

發(fā)布時(shí)間:2025/4/14 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、基本概念

  重載的運(yùn)算符時(shí)具有特殊名字的函數(shù):它們的名字由關(guān)鍵字operator和其后要定義的運(yùn)算符號(hào)共同組成。和其他函數(shù)一樣,重載的運(yùn)算符也包含返回類型、參數(shù)列表以及函數(shù)體。

  重載運(yùn)算符函數(shù)的參數(shù)數(shù)量與該運(yùn)算符作用的運(yùn)算對(duì)象數(shù)量一樣多。一元運(yùn)算符有一個(gè)參數(shù),二元運(yùn)算符有兩個(gè)。對(duì)于二元運(yùn)算符來(lái)說(shuō),左側(cè)運(yùn)算對(duì)象傳遞給第一個(gè)參數(shù),而右側(cè)運(yùn)算對(duì)象傳遞給第二個(gè)參數(shù)。除了重載的函數(shù)調(diào)用運(yùn)算符operator()之外,其他重載運(yùn)算符不能含有默認(rèn)實(shí)參。

  當(dāng)一個(gè)重載的運(yùn)算符時(shí)成員函數(shù)時(shí),this綁定到左側(cè)運(yùn)算對(duì)象。成員運(yùn)算符函數(shù)的顯式參數(shù)數(shù)量比運(yùn)算對(duì)象的數(shù)量少一個(gè)。

  對(duì)一個(gè)運(yùn)算符來(lái)說(shuō),它或者是類的成員,或者至少含有一個(gè)類類型的參數(shù)

  可以重載的運(yùn)算符:

+-*/%^
&|~!,=
<><=>=++--
<<>>==!=&&||
+=-=/=%=^=&=
|=*=<<=>>=[]()
->->*newnew []deletedelete []

  不能被重載的運(yùn)算符:

::.*.?:

  我們只能重載已有的運(yùn)算符,而無(wú)權(quán)發(fā)明新的運(yùn)算符號(hào)。對(duì)于一個(gè)重載的運(yùn)算符來(lái)說(shuō),其優(yōu)先級(jí)和結(jié)合律與對(duì)應(yīng)的內(nèi)置運(yùn)算符保持一致。

?1)直接調(diào)用一個(gè)重載的運(yùn)算符

  通用情況下,我們將運(yùn)算符作用于類型正確的實(shí)參,從而以這種間接方式“調(diào)用”重載的運(yùn)算符函數(shù)。然而,我們也能像調(diào)用普通函數(shù)一樣直接調(diào)用運(yùn)算符函數(shù),先指定函數(shù)名字,然后傳入數(shù)量正確、類型適當(dāng)?shù)膶?shí)參:

  // 一個(gè)非成員運(yùn)算符函數(shù)的等價(jià)調(diào)用
  data1+data2 // 普通的表達(dá)式
  operator+(data1,data2) // 等價(jià)的函數(shù)調(diào)用

  我們像調(diào)用其他成員函數(shù)一樣顯式地調(diào)用成員運(yùn)算符函數(shù)。首先指定運(yùn)算符函數(shù)的對(duì)象(或指針)的名字,然后使用點(diǎn)運(yùn)算符(或箭頭運(yùn)算符)訪問(wèn)希望調(diào)用的函數(shù):

  data1+=data2 // 基于“調(diào)用”的表達(dá)式
  data1.operator+=(data2) // 對(duì)成員運(yùn)算符函數(shù)的等價(jià)調(diào)用

2)某些運(yùn)算符不應(yīng)該被重載

  某些運(yùn)算符指定了運(yùn)算對(duì)象的求值的順序。因?yàn)槭褂弥剌d的運(yùn)算符本質(zhì)上是一次函數(shù)調(diào)用,所以這些關(guān)于運(yùn)算對(duì)象求值順序的規(guī)則無(wú)法應(yīng)用到重載的運(yùn)算符上。特別是,邏輯與運(yùn)算符、邏輯或運(yùn)算符和逗號(hào)運(yùn)算符的運(yùn)算對(duì)象求值順序規(guī)則無(wú)法保留下來(lái)。除此之外,&&和||運(yùn)算符的重載版本也無(wú)法保留內(nèi)置運(yùn)算符的短路求值屬性,兩個(gè)運(yùn)算對(duì)象總是會(huì)被求值。

  還有一個(gè)原因使得我們一般不重載逗號(hào)運(yùn)算符和取地址符:C++語(yǔ)言已經(jīng)定義了這兩種運(yùn)算符用于類類型對(duì)象時(shí)的特殊含義,這一點(diǎn)與大多數(shù)運(yùn)算符都不相同。因?yàn)檫@兩種運(yùn)算符已經(jīng)有了內(nèi)置的含義,所以一般來(lái)說(shuō)它們不應(yīng)該被重載,否則它們的行為將異于常態(tài),從而導(dǎo)致類的用戶無(wú)法適應(yīng)。

  通常情況下,不應(yīng)該重載逗號(hào)、取地址、邏輯與、邏輯或運(yùn)算符

3)使用與內(nèi)置類型一致的含義

  如果某些類操作在邏輯上與運(yùn)算符相關(guān),則它們適合定義成重載的運(yùn)算符:

  • 如果類執(zhí)行IO操作,則定義移位運(yùn)算符使其與內(nèi)置類型的IO保持一致。
  • 如果類的某個(gè)操作是檢查相等性,則定義operator==;如果類有了operator==,意味著它通常也應(yīng)該有operator!=。
  • 如果類包含一個(gè)內(nèi)在的單序比較操作,則定義operator<;如果類有了operator<,則它也應(yīng)該含有其他關(guān)系操作。
  • 重載運(yùn)算符的返回類型通常情況下應(yīng)該與其內(nèi)置版本的返回類型兼容:邏輯運(yùn)算符和關(guān)系運(yùn)算符應(yīng)該返回bool,算術(shù)運(yùn)算符應(yīng)該返回一個(gè)類類型的值,賦值運(yùn)算符和復(fù)合賦值運(yùn)算符則應(yīng)該返回左側(cè)運(yùn)算對(duì)象的一個(gè)引用。

4)賦值和復(fù)合賦值運(yùn)算符

  賦值運(yùn)算符的行為與復(fù)合版本的類似:賦值之后,左側(cè)運(yùn)算對(duì)象和右側(cè)運(yùn)算對(duì)象的值相等,并且運(yùn)算符應(yīng)該返回它左側(cè)運(yùn)算對(duì)象的一個(gè)引用。重載的賦值運(yùn)算符應(yīng)該繼承而非違背其內(nèi)置版本的含義。

  如果類含有算術(shù)運(yùn)算符或者位運(yùn)算符,則最好也提供對(duì)應(yīng)的復(fù)合賦值運(yùn)算符。

5)選擇作為成員或者非成員

  下面的準(zhǔn)則有助于我們?cè)趯⑦\(yùn)算符定義為成員函數(shù)還是普通的非成員函數(shù)做出抉擇:

  • 賦值(=)、下標(biāo)([])、調(diào)用(())和成員訪問(wèn)箭頭(->)運(yùn)算符必須還是成員。
  • 復(fù)合賦值運(yùn)算符一般來(lái)說(shuō)應(yīng)該是成員,但并非必須。
  • 改變對(duì)象狀態(tài)的運(yùn)算符或者與給定類型密切相關(guān)的運(yùn)算符,如遞增、遞減和解引用運(yùn)算符,通常應(yīng)該是成員。
  • 具有對(duì)稱性的運(yùn)算符可能轉(zhuǎn)換任一端的運(yùn)算對(duì)象,例如算術(shù)、相等性、關(guān)系和位運(yùn)算符等,通常應(yīng)該是普通的非成員函數(shù)。

  當(dāng)把運(yùn)算符定義成成員函數(shù)時(shí),它的左側(cè)運(yùn)算對(duì)象必須是運(yùn)算符所屬類的一個(gè)對(duì)象。

  當(dāng)把運(yùn)算符定義成普通的非成員函數(shù)時(shí),唯一的要求是是至少有一個(gè)運(yùn)算對(duì)象是類類型,并且兩個(gè)運(yùn)算對(duì)象都能精確無(wú)誤地轉(zhuǎn)換。

?

二、輸入和輸出運(yùn)算符

1、重載輸出運(yùn)算符<<

  通常情況下,輸出運(yùn)算符的第一個(gè)形參是非常量ostream對(duì)象的引用。之所以ostream是非常量是因?yàn)橄蛄鲗懭雰?nèi)容會(huì)改變其狀態(tài);而該形參是引用是因?yàn)槲覀儫o(wú)法直接復(fù)制一個(gè)ostream對(duì)象。

  第二個(gè)形參一般來(lái)說(shuō)是一個(gè)常量的引用,該常量是我們想要打印的類類型。第二個(gè)形參是引用的原因是我們希望避免復(fù)制實(shí)參;而之所以該形參是常量是因?yàn)橥ǔG闆r打印對(duì)象不會(huì)改變對(duì)象的內(nèi)容。

  為了與其他輸出運(yùn)算符保持一致,operator<<一般要返回它的ostream形參。

1 std::ostream &operator<<(std::ostream& os, const SalesData &item) 2 { 3 os << item.m_bookno << ", " << item.m_unitssold << ", " 4 << item.m_revenue << ", " << item.avgPrice(); 5 return os; 6 } View Code

1)輸入輸出運(yùn)算符必須是非成員函數(shù)

  與iostream標(biāo)準(zhǔn)庫(kù)兼容的輸入輸出運(yùn)算符必須是普通的非成員函數(shù),而不能是類的成員函數(shù),因?yàn)槲覀儫o(wú)法給標(biāo)準(zhǔn)的類添加任何成員。

  IO運(yùn)算符通常需要讀寫類的非公有數(shù)據(jù)成員,所以IO運(yùn)算符一般被聲明為友元。

?

2、重載輸入運(yùn)算符>>

  通常情況下,輸入運(yùn)算符的第一個(gè)形參是運(yùn)算符將要讀取的流的引用,第二個(gè)形參是將要讀入到的非常量對(duì)象的引用。該運(yùn)算符通常會(huì)返回某個(gè)給定流的引用。第二個(gè)形參之所以必須是個(gè)非常量是因?yàn)檩斎脒\(yùn)算符本身的目的就是將數(shù)據(jù)讀入到這個(gè)對(duì)象中。

  輸入運(yùn)算符必須處理輸入可能失敗的情況,而輸出運(yùn)算符不需要。

1 std::istream &operator>>(std::istream &is, SalesData &item) 2 { 3 double price; 4 is >> item.m_bookno >> item.m_unitssold >> price; 5 if (is) 6 item.m_revenue = item.m_unitssold*price; 7 else 8 item = SalesData(); // 輸入失敗,對(duì)象被賦予默認(rèn)的狀態(tài) 9 return is; 10 } View Code

1)輸入時(shí)的錯(cuò)誤

  在執(zhí)行輸入運(yùn)算符時(shí)可能發(fā)生以下錯(cuò)誤:

  • 當(dāng)流含有錯(cuò)誤類型的數(shù)據(jù)時(shí)讀取操作可能失敗。
  • 當(dāng)讀取到達(dá)文件末尾或者遇到輸入流的其他錯(cuò)誤時(shí)也會(huì)失敗。

?

三、算術(shù)和關(guān)系運(yùn)算符

?  通常情況下,我們把算術(shù)運(yùn)算符定義成非成員函數(shù)以允許對(duì)左側(cè)或右側(cè)的運(yùn)算對(duì)象進(jìn)行轉(zhuǎn)換。因?yàn)檫@些運(yùn)算符一般不需要改變運(yùn)算對(duì)象的狀態(tài),所以形參都是常量的引用。

  算術(shù)運(yùn)算通常會(huì)計(jì)算它的兩個(gè)運(yùn)算對(duì)象并得到一個(gè)新值,這個(gè)值有別于任意一個(gè)運(yùn)算對(duì)象,常常位于一個(gè)局部變量之內(nèi),操作完成后返回該變量的副本作為其結(jié)果。如果類定義了算術(shù)運(yùn)算符,則它一般也會(huì)定義一個(gè)對(duì)應(yīng)的復(fù)合賦值運(yùn)算符。此時(shí),最有效的方法是使用復(fù)合賦值運(yùn)算符來(lái)定義算術(shù)運(yùn)算符。

1 SalesData &SalesData::operator+=(const SalesData &rhs) 2 { 3 m_unitssold += rhs.m_unitssold; 4 m_revenue += rhs.m_revenue; 5 return *this; 6 } 7 8 SalesData operator+(const SalesData &lhs, const SalesData &rhs) 9 { 10 SalesData sum = lhs; 11 sum += rhs; 12 return sum; 13 } View Code

1、相等運(yùn)算符

  通常情況下,C++中的類通過(guò)相等運(yùn)算符來(lái)檢驗(yàn)兩個(gè)對(duì)象是否相等。也就是說(shuō),它們會(huì)比較對(duì)象的每一個(gè)數(shù)據(jù)成員,只有當(dāng)所有對(duì)應(yīng)的成員都相等時(shí)才認(rèn)為兩個(gè)對(duì)象相等。

1 bool operator==(const SalesData &lhs, const SalesData &rhs) 2 { 3 return lhs.m_bookno == rhs.m_bookno&& 4 lhs.m_unitssold == rhs.m_unitssold&& 5 lhs.m_revenue == rhs.m_revenue; 6 } 7 8 bool operator!=(const SalesData &lhs, const SalesData &rhs) 9 { 10 return !(lhs == rhs); 11 } View Code

2、關(guān)系運(yùn)算符

  定義了相等運(yùn)算符的類也常常(但不總是)包含關(guān)系運(yùn)算符。特別是,因?yàn)殛P(guān)聯(lián)容器和一些算法要用到小于運(yùn)算符,所以定義operator<會(huì)比較有用。

  通常情況下關(guān)系運(yùn)算符應(yīng)該:定義順序關(guān)系,令其與關(guān)聯(lián)容器中對(duì)關(guān)鍵字的要求一致。如果類同時(shí)也含有==運(yùn)算符的話,則定義一種關(guān)系令其與==保持一致。特別是,如果兩個(gè)對(duì)象是!=的話,那么一個(gè)對(duì)象應(yīng)該<另一個(gè)。

?

四、賦值運(yùn)算符

  我們可以重載賦值運(yùn)算符。不論形參的類型是什么,賦值運(yùn)算符都必須定義為成員函數(shù)。賦值運(yùn)算符返回其左側(cè)運(yùn)算對(duì)象的引用。

1)復(fù)合賦值運(yùn)算符

  復(fù)合賦值運(yùn)算符不非得是類的成員,不過(guò)我們還是傾向于把包括賦值在內(nèi)的所有賦值運(yùn)算都定義在類的內(nèi)部。為了與內(nèi)置類型的復(fù)合賦值保持一致,類中的復(fù)合賦值運(yùn)算符也要返回其左側(cè)運(yùn)算對(duì)象的引用。

?

五、下標(biāo)運(yùn)算符

  表示容器的類通常可以通過(guò)元素在容器中的位置訪問(wèn)元素,這些類一般會(huì)定義下標(biāo)運(yùn)算符operator[]。下標(biāo)運(yùn)算符必須是成員函數(shù)。

  為了與下標(biāo)的原始定義兼容,下標(biāo)運(yùn)算符通常以所訪問(wèn)元素的引用作為返回值,這樣做的好處是下標(biāo)可以出現(xiàn)在賦值運(yùn)算符的任意一端。進(jìn)一步,我們最好同時(shí)定義下標(biāo)運(yùn)算符的常量版本和非常量版本,當(dāng)作用于一個(gè)常量對(duì)象時(shí),下標(biāo)運(yùn)算符返回常量引用以確保我們不會(huì)給返回的對(duì)象賦值。

1 class StrVec 2 { 3 public: 4 StrVec():vec(){} 5 void push_back(const std::string &s) { vec.push_back(s); } 6 std::string &operator[](std::size_t n) { return vec[n]; } 7 const std::string &operator[](std::size_t n)const { return vec[n]; } 8 private: 9 std::vector<std::string> vec; 10 }; View Code

?

六、遞增和遞減運(yùn)算符

  定義遞增和遞減運(yùn)算符的類應(yīng)該同時(shí)定義前置版本和后置版本。這些運(yùn)算符通常應(yīng)該被定義成類的成員。

1)定義前置遞增/遞減運(yùn)算符

  為了與內(nèi)置版本保持一致,前置運(yùn)算符應(yīng)該返回遞增或遞減后對(duì)象的引用。

1 // 前置版本:返回遞增/遞減對(duì)象的引用 2 StrBlob &StrBlob::operator++() 3 { 4 ++curr; 5 check(curr, "increment past end"); 6 return *this; 7 } 8 9 StrBlob &StrBlob::operator--() 10 { 11 --curr; 12 check(curr, "decrement past end"); 13 return *this; 14 } View Code

2)區(qū)分前置和后置運(yùn)算符

  要想同時(shí)定義前置和后置運(yùn)算符,必須首先解決一個(gè)問(wèn)題,即普通的重載形式無(wú)法區(qū)分這兩種情況。前置和后置版本使用的是同一個(gè)符號(hào),意味著其重載版本所用的名字將是相同的,并且運(yùn)算對(duì)象的數(shù)量和類型也相同。

  為了解決這個(gè)問(wèn)題,后置版本接受一個(gè)額外的(不被使用)int類型的形參。當(dāng)我們使用后置運(yùn)算符時(shí),編譯器為這個(gè)形參提供一個(gè)值為0的實(shí)參。盡管從語(yǔ)法上來(lái)說(shuō)后置函數(shù)可以使用這個(gè)額外的形參,但是在實(shí)際過(guò)程中通常不會(huì)這么做。這個(gè)形參的唯一作用就是區(qū)分前置和后置版本的函數(shù),而不是真的要在實(shí)現(xiàn)后置版本時(shí)參與運(yùn)算。

1 // 后置版本 2 StrBlob StrBlob::operator++(int) 3 { 4 StrBlob ret = *this; 5 ++*this; 6 return ret; 7 } 8 9 StrBlob StrBlob::operator--(int) 10 { 11 StrBlob ret = *this; 12 --*this; 13 return ret; 14 } View Code

  因?yàn)槲覀儾粫?huì)用到int形參,所以無(wú)須為其命名。

完整代碼:

1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 #include <memory> 6 7 class StrBlob 8 { 9 public: 10 // 前置版本 11 StrBlob &operator++(); 12 StrBlob &operator--(); 13 // 后置版本 14 StrBlob operator++(int); 15 StrBlob operator--(int); 16 public: 17 typedef std::vector<std::string>::size_type size_type; 18 StrBlob(std::initializer_list<std::string> items) 19 :data(std::make_shared<std::vector<std::string>>(items)), curr(0) {} 20 size_type size()const { return data->size(); } 21 std::string now()const { return (*data)[curr]; } 22 23 private: 24 void check(size_type i, const std::string &msg) const 25 { 26 if (i >= data->size()) 27 throw std::out_of_range(msg); 28 } 29 private: 30 std::shared_ptr<std::vector<std::string>> data; // 多個(gè)對(duì)象間共享底層元素 31 std::size_t curr; // 在數(shù)組中的當(dāng)前位置 32 }; 33 34 // 前置版本:返回遞增/遞減對(duì)象的引用 35 StrBlob &StrBlob::operator++() 36 { 37 ++curr; 38 check(curr, "increment past end"); 39 return *this; 40 } 41 42 StrBlob &StrBlob::operator--() 43 { 44 --curr; 45 check(curr, "decrement past end"); 46 return *this; 47 } 48 // 后置版本 49 StrBlob StrBlob::operator++(int) 50 { 51 StrBlob ret = *this; 52 ++*this; 53 return ret; 54 } 55 56 StrBlob StrBlob::operator--(int) 57 { 58 StrBlob ret = *this; 59 --*this; 60 return ret; 61 } 62 63 int main() 64 { 65 StrBlob blob({ "a", "b","c","d","e" }); 66 std::cout << (blob++).now() << std::endl; 67 return 0; 68 } View Code

?

七、成員訪問(wèn)運(yùn)算符

  在迭代器及智能指針類中常常用到解引用運(yùn)算符(*)和箭頭運(yùn)算符(->)。箭頭運(yùn)算符必須是類的成員。解引用運(yùn)算符通常也是類的成員,盡管并非必須如此。

1 class StrBlob 2 { 3 public: 4 // 前置版本 5 StrBlob &operator++(); 6 StrBlob &operator--(); 7 // 后置版本 8 StrBlob operator++(int); 9 StrBlob operator--(int); 10 11 std::string &operator*()const { 12 return (*data)[curr]; 13 } 14 std::string *operator->()const { 15 return &this->operator*(); // 將實(shí)際工作委托給解引用運(yùn)算符 16 } 17 public: 18 typedef std::vector<std::string>::size_type size_type; 19 StrBlob(std::initializer_list<std::string> items) 20 :data(std::make_shared<std::vector<std::string>>(items)), curr(0) {} 21 size_type size()const { return data->size(); } 22 std::string now()const { return (*data)[curr]; } 23 24 private: 25 void check(size_type i, const std::string &msg) const 26 { 27 if (i >= data->size()) 28 throw std::out_of_range(msg); 29 } 30 private: 31 std::shared_ptr<std::vector<std::string>> data; // 多個(gè)對(duì)象間共享底層元素 32 std::size_t curr; // 在數(shù)組中的當(dāng)前位置 33 }; View Code

1)對(duì)箭頭運(yùn)算符返回值的限定

  和大多數(shù)其他運(yùn)算符一樣(盡管這么做不好),我們能令operator*完成任何我們指定的操作。箭頭運(yùn)算符則不是這樣,它永遠(yuǎn)不能丟掉成員訪問(wèn)這個(gè)最基本的含義。當(dāng)我們重載箭頭時(shí),可以改變的是箭頭從哪個(gè)對(duì)象中獲取成員,而箭頭獲取成員這一事實(shí)則永遠(yuǎn)不變。

  對(duì)于形如point->mem的表達(dá)式來(lái)說(shuō),point必須是指向類對(duì)象的指針或者是一個(gè)重載了operator->的類的對(duì)象。根據(jù)point類型不同,point->mem分別等價(jià)于

  (*point).mem;? // point是一個(gè)內(nèi)置的指針類型

  point.operator()->mem; // point是類的一個(gè)對(duì)象

除此之外,代碼都將發(fā)生錯(cuò)誤。point->mem的執(zhí)行過(guò)程如下所示:

  • 如果point是指針,則我們應(yīng)用內(nèi)置的箭頭運(yùn)算符,表達(dá)式等價(jià)于(*point).mem。首先解引用該指針,然后從所得的對(duì)象中獲取指定的成員。如果point所指的類型沒有名為mem的成員,程序發(fā)生錯(cuò)誤。
  • 如果point是定義了operator->的類的一個(gè)對(duì)象,則我們使用point.operator->()的結(jié)果來(lái)獲取mem。其中,如果該結(jié)果是一個(gè)指針,則執(zhí)行第1步;如果該結(jié)果本身含有重載的operator->(),則重復(fù)調(diào)用當(dāng)前步驟。最終,當(dāng)這一過(guò)程結(jié)束時(shí)程序或者返回了所需的內(nèi)容,或者返回一些表示程序錯(cuò)誤的信息。
  •   重載的箭頭運(yùn)算符必須返回類的指針或者自定義了箭頭運(yùn)算符的某個(gè)類的對(duì)象。

    ?

    一些完整的例子:

    1 #ifndef SALES_DATA 2 #define SALES_DATA 3 4 #include <iostream> 5 #include <string> 6 class SalesData 7 { 8 // 友元聲明 9 friend std::ostream &operator<<(std::ostream &os, const SalesData &item); 10 friend std::istream &operator>>(std::istream &, SalesData &); 11 friend SalesData operator+(const SalesData &, const SalesData &); 12 friend bool operator==(const SalesData &, const SalesData &); 13 friend bool operator!=(const SalesData &, const SalesData &); 14 public: 15 SalesData &operator+=(const SalesData &); 16 public: 17 SalesData(const std::string &s="") :m_bookno(s), m_unitssold(0), m_revenue(0) {} 18 SalesData(const std::string &s, unsigned n, double p) : 19 m_bookno(s), m_unitssold(n), m_revenue(p * n) {} 20 private: 21 double avgPrice() const; 22 23 std::string m_bookno; // 書名 24 unsigned m_unitssold; // 數(shù)量 25 double m_revenue; // 總價(jià) 26 }; 27 28 std::ostream &operator<<(std::ostream& os, const SalesData &item); 29 std::istream &operator>>(std::istream &, SalesData &); 30 SalesData operator+(const SalesData &, const SalesData &); 31 bool operator==(const SalesData &, const SalesData &); 32 bool operator!=(const SalesData &, const SalesData &); 33 #endif SalesData.h 1 #include "SalesData.h" 2 #include <string> 3 4 std::ostream &operator<<(std::ostream& os, const SalesData &item) 5 { 6 os << item.m_bookno << ", " << item.m_unitssold << ", " 7 << item.m_revenue << ", " << item.avgPrice(); 8 return os; 9 } 10 11 std::istream &operator>>(std::istream &is, SalesData &item) 12 { 13 double price; 14 is >> item.m_bookno >> item.m_unitssold >> price; 15 if (is) 16 item.m_revenue = item.m_unitssold*price; 17 else 18 item = SalesData(); // 輸入失敗,對(duì)象被賦予默認(rèn)的狀態(tài) 19 return is; 20 } 21 22 SalesData &SalesData::operator+=(const SalesData &rhs) 23 { 24 m_unitssold += rhs.m_unitssold; 25 m_revenue += rhs.m_revenue; 26 return *this; 27 } 28 29 SalesData operator+(const SalesData &lhs, const SalesData &rhs) 30 { 31 SalesData sum = lhs; 32 sum += rhs; 33 return sum; 34 } 35 36 bool operator==(const SalesData &lhs, const SalesData &rhs) 37 { 38 return lhs.m_bookno == rhs.m_bookno&& 39 lhs.m_unitssold == rhs.m_unitssold&& 40 lhs.m_revenue == rhs.m_revenue; 41 } 42 43 bool operator!=(const SalesData &lhs, const SalesData &rhs) 44 { 45 return !(lhs == rhs); 46 } 47 48 double SalesData::avgPrice() const 49 { 50 if (m_unitssold) 51 return m_revenue / m_unitssold; 52 else 53 return 0; 54 } SalesData.cpp 1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 #include <memory> 6 7 class StrBlob 8 { 9 public: 10 // 前置版本 11 StrBlob &operator++(); 12 StrBlob &operator--(); 13 // 后置版本 14 StrBlob operator++(int); 15 StrBlob operator--(int); 16 17 std::string &operator*()const { 18 return (*data)[curr]; 19 } 20 std::string *operator->()const { 21 return &this->operator*(); // 將實(shí)際工作委托給解引用運(yùn)算符 22 } 23 public: 24 typedef std::vector<std::string>::size_type size_type; 25 StrBlob(std::initializer_list<std::string> items) 26 :data(std::make_shared<std::vector<std::string>>(items)), curr(0) {} 27 size_type size()const { return data->size(); } 28 std::string now()const { return (*data)[curr]; } 29 30 private: 31 void check(size_type i, const std::string &msg) const 32 { 33 if (i >= data->size()) 34 throw std::out_of_range(msg); 35 } 36 private: 37 std::shared_ptr<std::vector<std::string>> data; // 多個(gè)對(duì)象間共享底層元素 38 std::size_t curr; // 在數(shù)組中的當(dāng)前位置 39 }; 40 41 // 前置版本:返回遞增/遞減對(duì)象的引用 42 StrBlob &StrBlob::operator++() 43 { 44 ++curr; 45 check(curr, "increment past end"); 46 return *this; 47 } 48 49 StrBlob &StrBlob::operator--() 50 { 51 --curr; 52 check(curr, "decrement past end"); 53 return *this; 54 } 55 // 后置版本 56 StrBlob StrBlob::operator++(int) 57 { 58 StrBlob ret = *this; 59 ++*this; 60 return ret; 61 } 62 63 StrBlob StrBlob::operator--(int) 64 { 65 StrBlob ret = *this; 66 --*this; 67 return ret; 68 } 69 70 int main() 71 { 72 StrBlob blob({ "a", "b","c","d","e" }); 73 std::cout << blob->size() << std::endl; 74 return 0; 75 } main.cpp

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/ACGame/p/10304257.html

    總結(jié)

    以上是生活随笔為你收集整理的重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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