運算子覆載知识课件

上传人:yulij****0329 文档编号:141729610 上传时间:2020-08-11 格式:PPT 页数:81 大小:549KB
返回 下载 相关 举报
運算子覆載知识课件_第1页
第1页 / 共81页
運算子覆載知识课件_第2页
第2页 / 共81页
運算子覆載知识课件_第3页
第3页 / 共81页
運算子覆載知识课件_第4页
第4页 / 共81页
運算子覆載知识课件_第5页
第5页 / 共81页
点击查看更多>>
资源描述

《運算子覆載知识课件》由会员分享,可在线阅读,更多相关《運算子覆載知识课件(81页珍藏版)》请在金锄头文库上搜索。

1、1,第十四章,運算子覆載,2,第十四章 運算子覆載,在C+語言中,程式設計師除了可以對函式(包含成員函式)進行覆載之外,也可以對運算符號進行覆載,以擴充運算符號的功能,此稱為運算子覆載(Operator Overloading)。當然由於運算子分為單元運算子、二元運算子、前置運算子、後置運算子,因此運算子的覆載也比函式覆載稍微複雜一些,因此我們將運算子覆載獨立出來在本章作詳細的介紹。,3,大綱,14.1運算子覆載的需求 14.2運算子覆載 14.3單元運算子的覆載 14.4二元運算子的覆載 14.5單元運算與二元運算同時存在的覆載 14.6 轉型運算子的覆載 14.6.1物件轉基本資料型態 1

2、4.6.2不同類別型態間的轉換 14.7=與= =運算子覆載 14.7.1=運算子覆載 14.7.2=運算子覆載 14.8運算子覆載 14.8.1運算子覆載 14.9本章回顧,5,14.1運算子覆載的需求,為了使程式設計更方便,C+允許某些運算子被另行定義一些新功能,以便處理由程式設計師所定義的資料型態,這就是運算子覆載的主要目的。 【註】: 在上述範例中,當然我們也可以於Matrix類別中定義一個Matrix Sum(Matrix Var)成員函式,並透過c=a.Sum(b);完成矩陣的相加,但這卻不如c=a+b;來得方便與直觀,因此運算子覆載仍有其必要性及方便性。,圖14-1 運算子覆載的

3、必要性,6,14.2運算子覆載,我們已經了解運算子覆載的用途後,本節將介紹如何實作運算子覆載。事實上,運算子覆載的實作方法與定義類別中的成員函式覆載相似,也就是在類別內宣告覆載運算子,以及在類別內或類別外具體定義覆載運算子的新運算行為。 覆載運算子需要先在類別內宣告,其宣告語法如下: 語法說明: (1)語法中的#代表的是運算子符號,例如+、-、-等等。 (2)運算子的運算可以區分為不需要回傳值及需要回傳值。若不需要回傳值,則回傳資料型態應宣告為void。,回傳資料型態 operator#(傳入引數);,7,14.2運算子覆載,(3)傳入引數與函式的傳入引數類似,但有些不同。運算子的運算對象可以

4、區分為單元運算(例如傳統的a+;)及二元運算(例如傳統的a+b;)。如果是二元運算則後面的運算元(第二個運算元)需設定為引數(前面的運算元不必設定為引數,因為這是在類別內定義,因此該類別的物件將自動隱含成為第一個運算元)。如果是單元運算,則又可以分為兩種狀況,如下所述。 (4)單元運算分為兩種狀況,一種是前置運算子(例如傳統的+a;),一種是後置運算子(例如傳統的a+;)。宣告前置運算子覆載時不需要指定引數,宣告後置運算子覆載時則需要設定引數為int。 (5)運算子的覆載還有一些限制如下:,8,限制一:覆載運算子需符合C+語法。 限制二:程式設計師無法新創運算子符號,只能針對C+原有的運算符號

5、進行覆載,同時有些運算子是無法被覆載的,整理如下:,14.2運算子覆載,表14-1 可進行覆載的運算子,9,14.2 運算子覆載,限制三:在可被覆載的運算子中,有些運算子只能被定義為單元運算子,如下表: 限制四:在可被覆載的運算子中,有些運算子可以被定義為單元運算子或二元運算子,如下表:,表14-2 不可進行覆載的運算子,表14-3 只能被定義為單元運算子,表14-4 可被定義為單元運算子或二元運算子,10,14.2運算子覆載,限制五:無法重新定義運算元的個數(如限制四與限制三的規定)。 限制六:無法重新定義運算子優先權。 限制七:無法覆蓋運算子的原有功能。也就是內建的資料型態無法使用運算子覆

6、載重新定義,例如下列語法欲重新定義兩浮點數相加是錯誤的語法。,11,14.2運算子覆載,當宣告運算子覆載後,即可在類別外定義運算子覆載的內容,語法如下: 語法說明: 我們也可以將宣告與定義合併於類別內,此時就不需指定類別名稱。而事實上,覆載運算子函式也屬於該類別的一個成員函式,我們稱之為覆載函式或覆載成員函式。,回傳資料型態 類別名稱:operator#(傳入引數) 定義運算子覆載的運算行為 ;,12,14.3單元運算子的覆載,在本節中,我們將介紹單元運算子的覆載,單元運算子分為前置運算子與後置運算子兩種,首先我們先複習第三章所介紹的前置運算子與後置運算子定義。 前置運算子(例如:+i): 運

7、算元進行加一或減一的動作後,再進行其他運用。 後置運算子(例如:i+): 運算元先進行其他運用,再進行加一或減一的動作。 對於前置運算子而言,其覆載宣告語法如下: 對於後置運算子而言,其覆載宣告語法如下:,回傳資料型態 operator#();,回傳資料型態 operator#(int);,13,14.3單元運算子的覆載,語法說明: (1)前置運算子覆載宣告與後置運算子覆載宣告的分別在於是否有傳入引數int(int是固定語法,無法修改為其他如float等資料型態)。 (2)前置運算子與後置運算子的運算內容可以不同。 (3)若無回傳資料,則回傳資料型態為void,此時若前置運算子與後置運算子的行

8、為相同,則無論是前置運算子或後置運算子都不會影響整個運算式的結果。 (4)若有回傳資料,則應該宣告回傳資料的資料型態,此時前置運算子應先進行運算行為,再回傳資料;後置運算子則應回傳原有資料再進行運算行為(這需要一些技巧)。,14,14.3單元運算子的覆載,範例: 【觀念範例14-1】:宣告及定義單元運算子+的覆載,使得對自訂類別Matrix2D具有運算功能,扮演前置運算子,將進行累加2,扮演後置運算子,將進行累加3。不論是前置或後置運算子都不會回值資料。 範例14-1:ch14_01.cpp(檔案位於隨書光碟 ch14ch14_01.cpp)。,15,16,14.3單元運算子的覆載,17,14

9、.3單元運算子的覆載,執行結果: 範例說明: (1)第1519行是+前置運算子的覆載定義。 (2)第2025行是+後置運算子的覆載定義。 (3)第42行的+ObjA會呼叫第1519行的覆載定義。 (4)第48行的ObjB+會呼叫第2025行的覆載定義。 (5)當我們覆載了+運算子之後,編譯器會根據作用運算元的資料型態來決定運算方法,舉例如下:,ObjA= | 2 , 2 | | 2 , 2 | - ObjB= | 3 , 3 | | 3 , 3 |,18,14.3單元運算子的覆載,在範例14-1中,若後置運算子也設定為矩陣內容+2,則由執行結果中,將看不出來後置運算子與前置運算子的差別,這是因

10、為我們並要求覆載的前置或後置運算子回傳資料。事實上,如果我們讓覆載的前置或後置運算子回傳資料,也能夠讓前置運算子與後置運算子的效果有所不同。 舉例來說,在C+中,若+作為前置運算子,則會先進行加一的動作後,再將結果回傳。若+作為後置運算子,則會先傳遞變數值,然後才進行加一的動作。如下圖:,19,14.3單元運算子的覆載,圖14-2 前置運算子 與後置運算子的差別,20,14.3單元運算子的覆載,【觀念及實用範例14-2】:參考+運算子的原意,覆載+的前置與後置運算子功能,使其可適用於Matrix2D類別的矩陣遞增運算。 範例14-2:ch14_02.cpp(檔案位於隨書光碟 ch14ch14_

11、02.cpp)。,21,22,14.3單元運算子的覆載,23,14.3單元運算子的覆載,24,14.3單元運算子的覆載,執行結果: 範例說明: (1)第1519行是+前置運算子的覆載定義。它會回傳一個Matrix2D類別的物件,由於前置運算子的原意是先進行運算再回傳運算結果,因此,回傳時只要將原本物件內容回傳即可,因此,我們透過this指標達成這項工作。 (2)第2026行是+後置運算子的覆載定義。雖然後置運算子的原意和前置運算子的原意恰好相反,但我們卻無法單純地將第17、18行的順序對調作為覆載運算定義,因為這會先遇到return而造成遞增運算未被執行,故我們先使用TempObj存放原始矩陣

12、內容,最後也是回傳TempObj,以符合後置運算子的原意。,原本ObjA= | 0 , 0 | | 0 , 0 | ObjB= | 0 , 0 | | 0 , 0 | 經ObjB=+ObjA;運算後 ObjA= | 1 , 1 | | 1 , 1 | ObjB= | 1 , 1 | | 1 , 1 | = 原本ObjC= | 0 , 0 | | 0 , 0 | ObjD= | 0 , 0 | | 0 , 0 | 經ObjD=ObjC+;運算後 ObjC= | 1 , 1 | | 1 , 1 | - ObjD= | 0 , 0 | | 0 , 0 |,25,14.4二元運算子的覆載,除了少數的單

13、元運算子,絕大多數的運算子都屬於二元運算子,也就是運算元有兩個,例如A%B的%取餘數就是一個二元運算子,其運算元有A與B兩個。在覆載二元運算子時,由於我們一定是定義在某類別內,因此,必定有一個物件是內定的運算元,在傳統加法中,被加數就是那一個運算元,例如ObjA+ObjB,我們應該把+運算子覆載在ObjA的所屬類別內。 除了內定的運算元外,二元運算子的另一個運算元的資料型態則必須明確定義於覆載運算子的宣告中,因此,覆載二元運算子的宣告語法如下: 語法說明: (1)二元運算一般都具有回傳值,如果沒有回傳值則可將回傳資料型態設為void。 (2)宣告時,變數名稱可以省略,但定義時變數名稱不可省略,

14、而且通常該變數會在函式內被使用。,回傳資料型態 operator#(另一個運算元的資料型態 變數名稱);,26,14.4二元運算子的覆載,舉例來說,假設X、Y、Z皆是Matrix2D類別的物件,其運算子呼叫運算子覆載函式的示意圖如下:,圖14-3 二元運算子覆載示意圖,27,14.4二元運算子的覆載,【觀念及實用範例14-3】:將Matrix2D矩陣類別(矩陣元素資料型態修正為double),加入二元運算子*乘法功能,乘法對象可以是矩陣,也可以是實數。其中矩陣相乘公式如下: 範例14-3:ch14_03.cpp(檔案位於隨書光碟 ch14ch14_03.cpp)。,28,29,14.4二元運算

15、子的覆載,30,14.4二元運算子的覆載,31,14.4二元運算子的覆載,執行結果: 範例說明: (1)第20行,宣告覆載*運算子,使其能夠應用於Matrix2D類別,進行矩陣*數學常數的運算,其定義(運算行為)紀錄於第2736行。 (2)第21行,宣告覆載*運算子,使其能夠應用於Matrix2D類別,進行矩陣*矩陣的運算,其定義(運算行為)紀錄於第3746行。 (3)第62行會呼叫第2736行(3將會被變數R接收,而this將指向物件ObjA)進行矩陣*數學常數的運算,並將回傳值存放於ObjC中。 (4)第65行會呼叫第3746行(ObjB將會被物件變數R接收,而this將指向物件ObjA)

16、進行矩陣*矩陣的運算,並將回傳值存放於ObjD中。,ObjA= | 2 , 4 | | 6 , 8 | ObjB= | 1 , 9 | | 4 , 16 | - ObjC=ObjA*3= | 6 , 12 | | 18 , 24 | ObjD=ObjA*ObjB= | 18 , 82 | | 38 , 182 |,32,14.5 單元運算與二元運算同時存在的覆載,不知讀者是否發現一個問題,單元運算的後置運算必須將傳遞引數設為int,而二元運算則必須將第二個運算元設為引數。這在允許進行單元運算及多元運算的運算子時(如-,*),是否可能會造成混淆?請回顧範例14-3的第20行,如果我們將其運算對象設為整數(int),並將運算子改為-號,請問我們想要進行的是負號單元運算子的覆載,還是減號二元運算子的覆載呢? 答案其實很簡單,因為同時允許進行單元運算及二元運算覆載的運算子是無法進行後置運算子覆載的,例如我們通常會以-a代表負a,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 中学教育 > 教学课件 > 高中课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号