




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
C程序設計運算符重載資料C程序設計運算符重載資料C程序設計運算符重載資料4.1運算符重載的概念1C程序設計運算符重載資料C程序設計運算符重載資料C程序設計運4.1運算符重載的概念24.1運算符重載的概念2運算符重載的概念語言允許重新定義已有的運算符,使其完成一些只在該特定類中使用的特定操作,這就是運算符重載如用加法“+”運算符進行兩個復數的相加。若有z1=2+3i,z2=4-8i,在數學中,可直接用“+”實現z31+z2,也就是將z1和z2的實部和虛部分別相加,z3=2+4+(3-8)6-5i。這時必須實現復數相加。比如用戶可以通過定義一個函數來實現復數相加3運算符重載的概念語言允許重新定義已有的運算符,使其完成一些只例4.1通過函數實現復數相加示例。聲明復數數
{:數據成員 ; 實部 ; 虛部:公有函數 (r=0,i=0):(r),(i){}構造函數 (); 輸出復數 (1,2); 復數加法};() 輸出復數{ (<0)<<<<<<"i"<<; 虛部為負 (0)<<<<; 虛部為0 <<<<“+”<<<<“i”<<; 虛部為負}……4例4.1通過函數實現復數相加示例。4例4.1通過函數實現復數相加示例。……(12){ z(z1+z2,z1+z2)定義復數對象 z; 返回復數}() 主函數(){ z1(2,3),z2(6,-5),z3; 定義復數對象 z1(); 輸出z1 z2(); 輸出z2 z3=(z1,z2); z312 z3(); 輸出z3 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:2+3i6-5i8-2i請按任意鍵繼續...在()函數體中的兩行代碼可以用“(z1+z2,z1+z2);”代替,“(z1+z2,z1+z2)”的含義是建立一個臨時復數對象,它的實部為z1+z2,虛部為z1+z2,在建立臨時對象的過程中調用了構造函數,語句將此臨時對象作為函數的返回值。5例4.1通過函數實現復數相加示例。程序運行時屏幕輸出如下:運算符重載能否像實數的加法運算一樣,直接用加號“+”來實現復數運算呢?例如在程序中直接用“z312”進行運算,這需要對運算符“+”進行重載。運算符重載的方法在實質上就是定義一個重載運算符的函數,在執行被重載的運算符時,系統將調用此函數實現相應的運算。運算符重載本質就是函數的重載。重載運算符的函數的原型如下:返回值類型運算符(形參表);例如將“+”用于類的加法運算運算符重載的函數原型可以為:(1,2);6運算符重載能否像實數的加法運算一樣,直接用加號“+”來實現復例4.2通過運算符重載實現復數相加的示例。<> 編譯預處理命令; 使用命名空間聲明復數數
{:數據成員 ; 實部 ; 虛部:公有函數 (r=0,i=0):(r),(i){}構造函數 (); 輸出復數 (12) {(z1+z2,z1+z2);}};() 輸出復數{ (<0)<<<<<<"i"<<; 虛部為負 (0)<<<<; 虛部為0 <<<<"+"<<<<"i"<<; 虛部為負}……上面的程序在2005,2005,和都能正常運行,但在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明7例4.2通過運算符重載實現復數相加的示例。上面的程序在例4.2通過運算符重載實現復數相加的示例。……(a,b){a+b;} 錯,重載運算符的函數的參數不能全部是的標準類型() 主函數(){ z1(2,3),z2(6,-5),z3; 定義復數對象 z1(); 輸出z1 z2(); 輸出z2 z3=z1+z2; 進行復數加法運算 z3(); 輸出z3 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:2+3i6-5i8-2i請按任意鍵繼續...8例4.2通過運算符重載實現復數相加的示例。程序運行時屏幕輸4.2運算符重載方式94.2運算符重載方式9運算符重載方式的運算符按參加運算的操作數個數可分為單目運算符、雙目運算符、三目運算符以及不確定目數運算符單目運算符只有一個操作數,例如(取反運算符),(負號運算符)等雙目運算符有兩個操作數參與運算,例如2+3(加法運算符),(賦值運運算符)等三目運算符有三個操作數參與運算,三目運算符只包括問號運算符,行例如不確定目數運算符是操作數個數不確定,可根據需要重載為不同的操作數個數,不確定目數運算符只包括函數調用運算符“()”在中只能重載單目運算符、雙目運算符及不確定目數運算符“()”10運算符重載方式的運算符按參加運算的操作數個數可分為單目運算4.2.1運算符重載為類的成員函數通過該類的對象來調用運算符函數,由于對象本身將作為一個操作數,因此要求第一個操作數的類型為用戶自定義類,參數表中的參數個數比操作數個數少一。下面是運算符重載為類的成員函數的一般形式:類名{:數據成員 ……:公有函數 返回值類型運算符(形參表)運算符重載為類的成員函數 ……}; 其中“運算符”是運算符函數的專用函數名。114.2.1運算符重載為類的成員函數通過該類的對象來調用運算用類的成員函數重載單目運算符單目運算符的運算符在一般情況下重載為類的成員函數時,形參表為空,以當前對象(即調用該運算符函數的對象)作為運算符唯一的操作數。
12用類的成員函數重載單目運算符單目運算符的運算符在一般情況下重例4.3單目運算符重載為類的成員函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (){();} 重載負號運算符“-”};() 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值6 i=; 對i進行求負號運算,等價于(); <<()<<; 輸出數據值-6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}13例4.3單目運算符重載為類的成員函數示例。13用類的成員函數重載雙目運算符雙目運算符重載為類的成員函數時,形參表中有一個參數,以當前對象作為運算符的左操作數,參數作為右操作數。14用類的成員函數重載雙目運算符雙目運算符重載為類的成員函數時,例4.4雙目運算符重載為類的成員函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 ()重載加法運算符“+” {(>+);} };() 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 對整型對象求加法運算,等價于(j); <<()<<"+"<<()<<"="<<()<<輸出數值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=15請按任意鍵繼續...15例4.4雙目運算符重載為類的成員函數示例。程序運行時屏幕輸4.2.2運算符重載為類的友元函數可以像將運算符重載為類的友元函數,這時參數表中的參數個數與操作數個相等,并且操作數的第一個操作數的類型不要求是用戶自定義類。下面是運算符重載為類的友元函數的一般形式:類名{:數據成員 ……:公有函數 返回值類型運算符(形參表)運算符重載為類的友元函數 ……}; 由于是友元函數,因此在函數原型前應加上關鍵字。164.2.2運算符重載為類的友元函數可以像將運算符重載為類的用類的友元函數重載單目運算符將單目運算符重載為類的友元函數時,友元函數形參表中有一個參數作為該運算符的操作數。17用類的友元函數重載單目運算符將單目運算符重載為類的友元函數時例4.5單目運算符重載為類的友元函數示例。<> 編譯預處理命令; 使用命名空間聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 ()重載負號運算符"-" {();}; };……在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明18例4.5單目運算符重載為類的友元函數示例。在6.0下會例4.5單目運算符重載為類的友元函數示例。……() 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值 i=; 對i進行求負號運算,等價于(i); <<()<<; 輸出數據值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6-6請按任意鍵繼續...19例4.5單目運算符重載為類的友元函數示例。程序運行時屏幕輸用類的友元函數重載雙目運算符將雙目運算符重載為類的友元函數時,友元函數形參表中包含有兩個參數,這兩個參數分別作為運算符的左、右操作數。20用類的友元函數重載雙目運算符將雙目運算符重載為類的友元函數時例4.6雙目運算符重載為類的友元函數示例。<> 編譯預處理命令; 使用命名空間聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (,) {(+);}重載"+",兩個操作數都是對象 (a,) {(a+);} 重載"+",第一操作數是標準類型 (&a,b) {(+b);} 重載"+",第二操作數是標準類型};……在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明21例4.6雙目運算符重載為類的友元函數示例。在6.0下會例4.6雙目運算符重載為類的友元函數示例。……() 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 等價于(),兩個操作數都是對象 <<()<<"+"<<()<<"="<<()<<; k=1+j; 1等價于(1),第一操作數是標準類型 <<1<<"+"<<()<<"="<<()<<輸出數值 k=i+2; 2等價于(i,2),第二操作數是標準類型 <<()<<"+"<<2<<"="<<()<<輸出數值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=151+9=106+2=8請按任意鍵繼續...22例4.6雙目運算符重載為類的友元函數示例。程序運行時屏幕輸4.2.3運算符重載為普通函數可以將運算符重載為普通函數,這時參數表中的參數個數與操作數個相等,并且第一個操作數的類型不要求是用戶自定義類。下面是運算符重載為普通函數的一般形式:返回值類型運算符(形參表);由于是普通函數,因此在函數原型前不應加上關鍵字。234.2.3運算符重載為普通函數可以將運算符重載為普通函數,用普通函數重載單目運算符將單目運算符重載為普通函數時,函數形參表中有一個參數作為該運算符的操作數。24用普通函數重載單目運算符將單目運算符重載為普通函數時,函數形例4.7單目運算符重載為類的普通函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值};() 重載負號運算符"-"{(());}; () 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值6 i=; 對i進行求負號運算,等價于(i); <<()<<; 輸出數據值-6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}25例4.7單目運算符重載為類的普通函數示例。25用普通函數重載重載雙目運算符將雙目運算符重載為普通函數時,函數形參表中包含有兩個參數,這兩個參數分別作為運算符的左、右操作數。26用普通函數重載重載雙目運算符將雙目運算符重載為普通函數時,函例4.8雙目運算符重載為普通函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值};(,)重載運算符"+"{(()+());} () 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 對整型對象求加法運算,等價于() <<()<<"+"<<()<<"="<<()<<; (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=15請按任意鍵繼續...27例4.8雙目運算符重載為普通函數示例。程序運行時屏幕輸出如運算符重載一般地講,單目運算符最好重載為類的成員函數,雙目運算符最好重載為類的友元函數或普通函數。28運算符重載一般地講,單目運算符最好重載為類的成員函數,雙目運*4.3典型運算符重載29*4.3典型運算符重載29*4.3.1重載賦值運算符“=”由于賦值運算符重載后實現將一個表達式的值賦值給用戶自定義對象,也就是賦值運算符的第一個操作數是類型為用戶自定義類的對象,因此規定賦值運算符“=”只能重載為類的成員函數,一般重載格式為:類名類名(類名&源對象){ (&源對象) { 目的對象與源對象不是同一個對象 …… 復制被被賦值對象 } *; 返回目的對象}30*4.3.1重載賦值運算符“=”由于賦值運算符重載后實現*重載賦值運算符“=”如用戶沒有為一個類重載賦值運算符,編譯程序將生成一個默認賦值運算符函數。賦值運算把源對象的數據成員逐個地復制到目的對象的相應數據成員對于一般的類,使用默認賦值運算符函數都能正常地工作,但當一個類中包含有指針類型的數據成員,并且通過指針在構造函數中動態申請了存儲空間,在析構函數中通過指針釋放了動態存儲空間,這種情況可能會出現運行時錯誤31*重載賦值運算符“=”如用戶沒有為一個類重載賦值運算符,編例4.9使用賦值運算符出現運行時錯誤的示例。
{:數據成員 *; 串值:公有成員 (*s="") 構造函數 { (s)s=""; 將空指針轉化為空串 =[(s)+1]; 分配存儲空間 (,s); 復制串值 } () 復制構造函數 { =[()+1]分配空間 (,); 復制串值 } (){[];} 析構函數 (){<<<<;} 顯示串};……32例4.9使用賦值運算符出現運行時錯誤的示例。32例4.9使用賦值運算符出現運行時錯誤的示例?!?) 主函數(){ s1(""),s2; 定義對象 s2=s1; 使用默認賦值運算符函數 s1(); 顯示串s1 s2(); 顯示串s2 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:請按任意鍵繼續...當用戶按任一鍵時,屏幕將會顯示類似!的錯誤在和環境中沒有出上述錯誤現象,原因是在發現釋放一個已釋放的空間時,不再作釋放操作,也不作異常處理33例4.9使用賦值運算符出現運行時錯誤的示例。程序運行時屏幕在執行“s1("");”語句時,構造函數動態地分配存儲空間,并將返回的地址賦給對象s1的數據成員,然后把“”拷貝到這塊空間中執行語句“s2=s1;”時,由于沒有為類重載賦值運算符,系統將調用默認賦值運算符函數,負責將對象s1的數據成員中存放的地址值賦值給對象s2的數據成員對象s1復制給對象s2的僅是其數據成員的值,并沒有把指向的動態存儲空間進行復制,當遇到對象的生命期結束需要撤銷對象時,首先由s2對象調用析構函數,將成員所指向的字符串“”所在的動態空間釋放在對象s1自動調用析構函數之前,對象s1的數據成員指向已釋放的內存空間,因此在s1調用析構函數時,無法正確執行析構函數代碼“[]”,從而導致出錯。34在執行“s1("");”語句時,構造函數動態地分配存儲空間重載賦值運算符解決問題應重載賦值運算符,復制指針數據成員所指向的動態空間中的內容。這樣,兩個對象的指針成員就擁有不同的地址值,指向不同的動態存儲空間35重載賦值運算符解決問題應重載賦值運算符,復制指針數據成員所指例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副作用。
{:數據成員 *; 串值:公有成員 (*s="") 構造函數 { (s)s=""; 將空指針轉化為空串 =[(s)+1]分配存儲空間 (,s); 復制串值 } () 復制構造函數 { =[()+1]分配空間 (,); 復制串值 } (); 重載賦值運算符 (){[];} 析構函數 (){<<<<;} 顯示串};……36例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副作用?!?) 重載賦值運算符{ () { 目的對象與源對象不是同一個對象 =[()+1]分配空間 (,)復制串值 } *; 返回目的對象}() 主函數(){ s1(""),s2; 定義對象 s2=s1; 使用重載賦值運算符 s1(); 顯示串s1 s2(); 顯示串s2 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:請按任意鍵繼續...37例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副4.3.2重載自增1運算符“”和自減1運算符“”這兩個運算符還有前綴和后綴的差別,和是前綴使用方式,和是后綴使用方式在當前的標準中,對此作了特殊約定,對于前綴使用方式,與一般單目運符的重載方式相同,對于后綴使用方式,在進行運算符的重載函數中增加一個整型參數具體重載函數的聲明格式如下:類名(); 前綴“”重載為類的成員函數類名(); 后綴“”重載為類的成員函數類名(); 前綴“”重載為類的成員函數類名(); 后綴“”重載為類的成員函數類名(類名&); 前綴“”重載為類的友元函數類名(類名&,); 后綴“”重載為類的友元函數類名(類名&); 前綴“”重載為類的友元函數類名(類名&,); 后綴“”重載為類的友元函數類名(類名&); 前綴“”重載為普通函數類名(類名&,); 后綴“”重載為普通函數類名(類名&); 前綴“”重載為普通函數類名(類名&,); 后綴“”重載為普通函數384.3.2重載自增1運算符“”和自減1運算符“”這兩個運例4.11重載自增1運算符“”和自減1運算符“”示例。
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (){();} 前綴“ (i){();} 后綴 () 前綴 {();} };(,i) 重載后綴為普通函數{ =a; 用暫存a a=(()-1); a的值減1 ; 返回a原來的值,也就是} …… 39例4.11重載自增1運算符“”和自減1運算符“”示例。39例4.11重載自增1運算符“”和自減1運算符“”示例?!?) 主函數(){ i,j; 定義整型對象 (6); 設置數據值 j=; 對i作前綴自增1運算等價于() <<()<<","<<()<<; 輸出數據值7,7 (6); 設置數據值 j=; 對i作后綴自增1運算等價于(0) <<()<<","<<()<<; 輸出數據值7,6 (6); 設置數據值 j=; 對i作前綴自減1運算等價于(i) <<()<<","<<()<<; 輸出數據值5,5 (6); 設置數據值 j=; 對i作后綴自減1運算等價于(i,0) <<()<<","<<()<<; 輸出數據值5,6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}40例4.11重載自增1運算符“”和自減1運算符“”示例。40*4.3.3重載下標運算符“[]”下標運算符“[]”一般用于在數組中標識數組元素的位置,在語言中,下標運算符“[]”是沒有越界檢查功能的??梢酝ㄟ^重載下標運算符“[]”實現一種更安全、功能更強的數組類型下標運算符的使用方式是a[i],第一個操作數為數組名,重載后就為用戶自定義對象,因此規定重載下標運算符“[]”只能重載為類的成員函數。定義下標運算符“[]”的函數重載的一般聲明格式如下:返回值類型[]();41*4.3.3重載下標運算符“[]”下標運算符“[]”一例4.12重載下標運算符“[]”示例。聲明數組類模板<>
{:數據成員 *; 存儲數據元素值 ; 數組元素個數:公有函數 ():(){=[];} 構造函數 (){;} 析構函數 [](i) 下標運算符"[]"重載為成員函數 { (i<0i>=) { <<"元素位置錯!"<<; (1); 退出程序的運行,返回到操作系統 } [i]; 返回[i] }};……42例4.12重載下標運算符“[]”示例。42例4.12重載下標運算符“[]”示例?!?) 主函數(){ a[]={1,9,7,5,6,3}; 定義數組a n=6; 數組元素個數 <>(n); 定義數組對象 i; 定義臨時變量 (i=0;i<n;)[i]=a[i][i]等價于[i] (i=0;i<n;)<<[i]<<""輸出元素值 <<; 換行 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:197563請按任意鍵繼續...43例4.12重載下標運算符“[]”示例。程序運行時屏幕輸出如*4.3.4重載函數調用運算符“()”重載函數調用運算符“()”的用途是使類的對象可以象函數名稱一樣使用,運算符“()”是通過用戶自定義對象來調用函數,也就是用戶自定義對象是第一個操作數,因此規定函數調用運算符“()”只能重載為類的成員函數,具體聲明格式如下:返回值類型()(形參表);在C中,由于上面的聲明格式中形參表的參數個數不確定,因此“()”是不確定目數運算符44*4.3.4重載函數調用運算符“()”重載函數調用運算符例4.13重載下標運算符“[]”示例。聲明數組類模板<>
{:數據成員 *; 存儲數據元素值 ; 數組元素個數:公有函數 ():(){=[];} 構造函數 (){;} 析構函數 ()(i)函數調用運算符只能重載為成員函數 { (i<0i>=) { <<"元素位置錯!"<<; (1); 退出程序的行運,返回到操作系統 } [i]; 返回[i] }};……45例4.13重載下標運算符“[]”示例。45例4.13重載下標運算符“[]”示例?!?) 主函數(){ a[]={1,9,7,5,6,3}; 定義數組a n=6; 數組元素個數 <>(n); 定義數組對象 i; 定義臨時變量 (i=0;i<n;)(i)=a[i](i)等價于(i) (i=0;i<n;)<<(i)<<""; 輸出元素值 <<; 換行 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}本例的函數調用運算符“()”的重載函數“()(i)”的返回值是關于類型的引用,也就是實際上返回一個變量的別名,可使函數調用運算“()”的重載函數的調用出現在賦值語句的左邊,這樣增加了程序靈活性。程序運行時屏幕輸出如下:197563請按任意鍵繼續...46例4.13重載下標運算符“[]”示例。本例的函數調用運算符*4.3.5重載輸入運算符“>>”和輸出運算符“<<”和分別是標準輸入流和標準輸出流。只要包含頭文件“”或“”,輸入運算符“>>”和輸出運算符“<<”就能對標準類型數據進行輸入和輸出。對于用戶自定義的對象,是不能直接用“<<”和“>>”來進行輸出和輸入的。如果要用它們輸出和輸入自定義的對象,必須對它們進行重載。輸入運算符“>>”和輸出運算符“<<”的重載函數的聲明一般形如下:>>(&,類名&); 重載友元函數<<(&,類名&)重載友元函數>>(&,類名&); 重載為普通函數<<(&,類名&); 重載為普通函數運算符“>>”和“<<”的第一個參數為類型為或的引用,重載函數不能過通用戶自定義對象來進行調用,所以只能將“>>”和“<<”的重載函數聲明為類的友元函數或普通的函數。47*4.3.5重載輸入運算符“>>”和輸出運算符“<<”和分例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。聲明復數數
{:數據成員 ; 實部 ; 虛部:公有函數 (r=0,i=0):(r),(i){}構造函數 (){;} 返回實部 (){;} 返回虛部 (r){=r;} 設置實部 (i){=i;} 設置虛部};……48例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。……>>(,)重載輸入運算符>>{ r,i; 表示實部(r)和虛部(i) <<"輸入實部:"; >>r; 輸入實部 <<"輸入虛部:"; >>i; 輸入虛部 (r); 設置實部 (i); 設置虛部 ; 返回輸入流對象}<<(,)重載運算符<<{ (()<0) <<()<<()<<"i"; 虛部為負 (()0) <<(); 虛部為0 <<()<<"+"<<()<<"i"虛部為正 ; 返回輸出流對象}……49例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。……intmain() //主函數main(){ Complexz; //定義復數對象 cin>>z; //輸入z,cin>>z等價于operator>>(cin,z) cout<<z<<endl; //輸出z,cout<<z等價于operator<<(cout,z) system("PAUSE"); //輸出系統提示信息 return0; //返回值0,返回操作系統}程序運行時屏幕輸出參考如下:輸入實部:6輸入虛部:86+8i請按任意鍵繼續...50例4.14重載輸入運算符“>>”和輸出運算符“<<”示例。 謝謝大家!51 謝謝大家!51C程序設計運算符重載資料C程序設計運算符重載資料C程序設計運算符重載資料4.1運算符重載的概念52C程序設計運算符重載資料C程序設計運算符重載資料C程序設計運4.1運算符重載的概念534.1運算符重載的概念2運算符重載的概念語言允許重新定義已有的運算符,使其完成一些只在該特定類中使用的特定操作,這就是運算符重載如用加法“+”運算符進行兩個復數的相加。若有z1=2+3i,z2=4-8i,在數學中,可直接用“+”實現z31+z2,也就是將z1和z2的實部和虛部分別相加,z3=2+4+(3-8)6-5i。這時必須實現復數相加。比如用戶可以通過定義一個函數來實現復數相加54運算符重載的概念語言允許重新定義已有的運算符,使其完成一些只例4.1通過函數實現復數相加示例。聲明復數數
{:數據成員 ; 實部 ; 虛部:公有函數 (r=0,i=0):(r),(i){}構造函數 (); 輸出復數 (1,2); 復數加法};() 輸出復數{ (<0)<<<<<<"i"<<; 虛部為負 (0)<<<<; 虛部為0 <<<<“+”<<<<“i”<<; 虛部為負}……55例4.1通過函數實現復數相加示例。4例4.1通過函數實現復數相加示例。……(12){ z(z1+z2,z1+z2)定義復數對象 z; 返回復數}() 主函數(){ z1(2,3),z2(6,-5),z3; 定義復數對象 z1(); 輸出z1 z2(); 輸出z2 z3=(z1,z2); z312 z3(); 輸出z3 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:2+3i6-5i8-2i請按任意鍵繼續...在()函數體中的兩行代碼可以用“(z1+z2,z1+z2);”代替,“(z1+z2,z1+z2)”的含義是建立一個臨時復數對象,它的實部為z1+z2,虛部為z1+z2,在建立臨時對象的過程中調用了構造函數,語句將此臨時對象作為函數的返回值。56例4.1通過函數實現復數相加示例。程序運行時屏幕輸出如下:運算符重載能否像實數的加法運算一樣,直接用加號“+”來實現復數運算呢?例如在程序中直接用“z312”進行運算,這需要對運算符“+”進行重載。運算符重載的方法在實質上就是定義一個重載運算符的函數,在執行被重載的運算符時,系統將調用此函數實現相應的運算。運算符重載本質就是函數的重載。重載運算符的函數的原型如下:返回值類型運算符(形參表);例如將“+”用于類的加法運算運算符重載的函數原型可以為:(1,2);57運算符重載能否像實數的加法運算一樣,直接用加號“+”來實現復例4.2通過運算符重載實現復數相加的示例。<> 編譯預處理命令; 使用命名空間聲明復數數
{:數據成員 ; 實部 ; 虛部:公有函數 (r=0,i=0):(r),(i){}構造函數 (); 輸出復數 (12) {(z1+z2,z1+z2);}};() 輸出復數{ (<0)<<<<<<"i"<<; 虛部為負 (0)<<<<; 虛部為0 <<<<"+"<<<<"i"<<; 虛部為負}……上面的程序在2005,2005,和都能正常運行,但在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明58例4.2通過運算符重載實現復數相加的示例。上面的程序在例4.2通過運算符重載實現復數相加的示例?!?a,b){a+b;} 錯,重載運算符的函數的參數不能全部是的標準類型() 主函數(){ z1(2,3),z2(6,-5),z3; 定義復數對象 z1(); 輸出z1 z2(); 輸出z2 z3=z1+z2; 進行復數加法運算 z3(); 輸出z3 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:2+3i6-5i8-2i請按任意鍵繼續...59例4.2通過運算符重載實現復數相加的示例。程序運行時屏幕輸4.2運算符重載方式604.2運算符重載方式9運算符重載方式的運算符按參加運算的操作數個數可分為單目運算符、雙目運算符、三目運算符以及不確定目數運算符單目運算符只有一個操作數,例如(取反運算符),(負號運算符)等雙目運算符有兩個操作數參與運算,例如2+3(加法運算符),(賦值運運算符)等三目運算符有三個操作數參與運算,三目運算符只包括問號運算符,行例如不確定目數運算符是操作數個數不確定,可根據需要重載為不同的操作數個數,不確定目數運算符只包括函數調用運算符“()”在中只能重載單目運算符、雙目運算符及不確定目數運算符“()”61運算符重載方式的運算符按參加運算的操作數個數可分為單目運算4.2.1運算符重載為類的成員函數通過該類的對象來調用運算符函數,由于對象本身將作為一個操作數,因此要求第一個操作數的類型為用戶自定義類,參數表中的參數個數比操作數個數少一。下面是運算符重載為類的成員函數的一般形式:類名{:數據成員 ……:公有函數 返回值類型運算符(形參表)運算符重載為類的成員函數 ……}; 其中“運算符”是運算符函數的專用函數名。624.2.1運算符重載為類的成員函數通過該類的對象來調用運算用類的成員函數重載單目運算符單目運算符的運算符在一般情況下重載為類的成員函數時,形參表為空,以當前對象(即調用該運算符函數的對象)作為運算符唯一的操作數。
63用類的成員函數重載單目運算符單目運算符的運算符在一般情況下重例4.3單目運算符重載為類的成員函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (){();} 重載負號運算符“-”};() 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值6 i=; 對i進行求負號運算,等價于(); <<()<<; 輸出數據值-6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}64例4.3單目運算符重載為類的成員函數示例。13用類的成員函數重載雙目運算符雙目運算符重載為類的成員函數時,形參表中有一個參數,以當前對象作為運算符的左操作數,參數作為右操作數。65用類的成員函數重載雙目運算符雙目運算符重載為類的成員函數時,例4.4雙目運算符重載為類的成員函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 ()重載加法運算符“+” {(>+);} };() 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 對整型對象求加法運算,等價于(j); <<()<<"+"<<()<<"="<<()<<輸出數值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=15請按任意鍵繼續...66例4.4雙目運算符重載為類的成員函數示例。程序運行時屏幕輸4.2.2運算符重載為類的友元函數可以像將運算符重載為類的友元函數,這時參數表中的參數個數與操作數個相等,并且操作數的第一個操作數的類型不要求是用戶自定義類。下面是運算符重載為類的友元函數的一般形式:類名{:數據成員 ……:公有函數 返回值類型運算符(形參表)運算符重載為類的友元函數 ……}; 由于是友元函數,因此在函數原型前應加上關鍵字。674.2.2運算符重載為類的友元函數可以像將運算符重載為類的用類的友元函數重載單目運算符將單目運算符重載為類的友元函數時,友元函數形參表中有一個參數作為該運算符的操作數。68用類的友元函數重載單目運算符將單目運算符重載為類的友元函數時例4.5單目運算符重載為類的友元函數示例。<> 編譯預處理命令; 使用命名空間聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 ()重載負號運算符"-" {();}; };……在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明69例4.5單目運算符重載為類的友元函數示例。在6.0下會例4.5單目運算符重載為類的友元函數示例?!?) 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值 i=; 對i進行求負號運算,等價于(i); <<()<<; 輸出數據值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6-6請按任意鍵繼續...70例4.5單目運算符重載為類的友元函數示例。程序運行時屏幕輸用類的友元函數重載雙目運算符將雙目運算符重載為類的友元函數時,友元函數形參表中包含有兩個參數,這兩個參數分別作為運算符的左、右操作數。71用類的友元函數重載雙目運算符將雙目運算符重載為類的友元函數時例4.6雙目運算符重載為類的友元函數示例。<> 編譯預處理命令; 使用命名空間聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (,) {(+);}重載"+",兩個操作數都是對象 (a,) {(a+);} 重載"+",第一操作數是標準類型 (&a,b) {(+b);} 重載"+",第二操作數是標準類型};……在6.0下會出現的編譯時錯語,是6.0的一個,在6.0中可將:<> 編譯預處理命令; 使用命名空間改為:<> 編譯預處理命令<> 包含()的聲明72例4.6雙目運算符重載為類的友元函數示例。在6.0下會例4.6雙目運算符重載為類的友元函數示例?!?) 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 等價于(),兩個操作數都是對象 <<()<<"+"<<()<<"="<<()<<; k=1+j; 1等價于(1),第一操作數是標準類型 <<1<<"+"<<()<<"="<<()<<輸出數值 k=i+2; 2等價于(i,2),第二操作數是標準類型 <<()<<"+"<<2<<"="<<()<<輸出數值 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=151+9=106+2=8請按任意鍵繼續...73例4.6雙目運算符重載為類的友元函數示例。程序運行時屏幕輸4.2.3運算符重載為普通函數可以將運算符重載為普通函數,這時參數表中的參數個數與操作數個相等,并且第一個操作數的類型不要求是用戶自定義類。下面是運算符重載為普通函數的一般形式:返回值類型運算符(形參表);由于是普通函數,因此在函數原型前不應加上關鍵字。744.2.3運算符重載為普通函數可以將運算符重載為普通函數,用普通函數重載單目運算符將單目運算符重載為普通函數時,函數形參表中有一個參數作為該運算符的操作數。75用普通函數重載單目運算符將單目運算符重載為普通函數時,函數形例4.7單目運算符重載為類的普通函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值};() 重載負號運算符"-"{(());}; () 主函數(){ i; 定義整型對象 (6); 設置數據值 <<()<<; 輸出數據值6 i=; 對i進行求負號運算,等價于(i); <<()<<; 輸出數據值-6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}76例4.7單目運算符重載為類的普通函數示例。25用普通函數重載重載雙目運算符將雙目運算符重載為普通函數時,函數形參表中包含有兩個參數,這兩個參數分別作為運算符的左、右操作數。77用普通函數重載重載雙目運算符將雙目運算符重載為普通函數時,函例4.8雙目運算符重載為普通函數示例。聲明整型類
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值};(,)重載運算符"+"{(()+());} () 主函數(){ i(6),j(9),k; 定義整型對象 k=i+j; 對整型對象求加法運算,等價于() <<()<<"+"<<()<<"="<<()<<; (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:6+9=15請按任意鍵繼續...78例4.8雙目運算符重載為普通函數示例。程序運行時屏幕輸出如運算符重載一般地講,單目運算符最好重載為類的成員函數,雙目運算符最好重載為類的友元函數或普通函數。79運算符重載一般地講,單目運算符最好重載為類的成員函數,雙目運*4.3典型運算符重載80*4.3典型運算符重載29*4.3.1重載賦值運算符“=”由于賦值運算符重載后實現將一個表達式的值賦值給用戶自定義對象,也就是賦值運算符的第一個操作數是類型為用戶自定義類的對象,因此規定賦值運算符“=”只能重載為類的成員函數,一般重載格式為:類名類名(類名&源對象){ (&源對象) { 目的對象與源對象不是同一個對象 …… 復制被被賦值對象 } *; 返回目的對象}81*4.3.1重載賦值運算符“=”由于賦值運算符重載后實現*重載賦值運算符“=”如用戶沒有為一個類重載賦值運算符,編譯程序將生成一個默認賦值運算符函數。賦值運算把源對象的數據成員逐個地復制到目的對象的相應數據成員對于一般的類,使用默認賦值運算符函數都能正常地工作,但當一個類中包含有指針類型的數據成員,并且通過指針在構造函數中動態申請了存儲空間,在析構函數中通過指針釋放了動態存儲空間,這種情況可能會出現運行時錯誤82*重載賦值運算符“=”如用戶沒有為一個類重載賦值運算符,編例4.9使用賦值運算符出現運行時錯誤的示例。
{:數據成員 *; 串值:公有成員 (*s="") 構造函數 { (s)s=""; 將空指針轉化為空串 =[(s)+1]; 分配存儲空間 (,s); 復制串值 } () 復制構造函數 { =[()+1]分配空間 (,); 復制串值 } (){[];} 析構函數 (){<<<<;} 顯示串};……83例4.9使用賦值運算符出現運行時錯誤的示例。32例4.9使用賦值運算符出現運行時錯誤的示例。……() 主函數(){ s1(""),s2; 定義對象 s2=s1; 使用默認賦值運算符函數 s1(); 顯示串s1 s2(); 顯示串s2 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:請按任意鍵繼續...當用戶按任一鍵時,屏幕將會顯示類似!的錯誤在和環境中沒有出上述錯誤現象,原因是在發現釋放一個已釋放的空間時,不再作釋放操作,也不作異常處理84例4.9使用賦值運算符出現運行時錯誤的示例。程序運行時屏幕在執行“s1("");”語句時,構造函數動態地分配存儲空間,并將返回的地址賦給對象s1的數據成員,然后把“”拷貝到這塊空間中執行語句“s2=s1;”時,由于沒有為類重載賦值運算符,系統將調用默認賦值運算符函數,負責將對象s1的數據成員中存放的地址值賦值給對象s2的數據成員對象s1復制給對象s2的僅是其數據成員的值,并沒有把指向的動態存儲空間進行復制,當遇到對象的生命期結束需要撤銷對象時,首先由s2對象調用析構函數,將成員所指向的字符串“”所在的動態空間釋放在對象s1自動調用析構函數之前,對象s1的數據成員指向已釋放的內存空間,因此在s1調用析構函數時,無法正確執行析構函數代碼“[]”,從而導致出錯。85在執行“s1("");”語句時,構造函數動態地分配存儲空間重載賦值運算符解決問題應重載賦值運算符,復制指針數據成員所指向的動態空間中的內容。這樣,兩個對象的指針成員就擁有不同的地址值,指向不同的動態存儲空間86重載賦值運算符解決問題應重載賦值運算符,復制指針數據成員所指例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副作用。
{:數據成員 *; 串值:公有成員 (*s="") 構造函數 { (s)s=""; 將空指針轉化為空串 =[(s)+1]分配存儲空間 (,s); 復制串值 } () 復制構造函數 { =[()+1]分配空間 (,); 復制串值 } (); 重載賦值運算符 (){[];} 析構函數 (){<<<<;} 顯示串};……87例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副作用?!?) 重載賦值運算符{ () { 目的對象與源對象不是同一個對象 =[()+1]分配空間 (,)復制串值 } *; 返回目的對象}() 主函數(){ s1(""),s2; 定義對象 s2=s1; 使用重載賦值運算符 s1(); 顯示串s1 s2(); 顯示串s2 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}程序運行時屏幕輸出如下:請按任意鍵繼續...88例4.10重載賦值運算符避免例4.9使用默認賦值運算符的副4.3.2重載自增1運算符“”和自減1運算符“”這兩個運算符還有前綴和后綴的差別,和是前綴使用方式,和是后綴使用方式在當前的標準中,對此作了特殊約定,對于前綴使用方式,與一般單目運符的重載方式相同,對于后綴使用方式,在進行運算符的重載函數中增加一個整型參數具體重載函數的聲明格式如下:類名(); 前綴“”重載為類的成員函數類名(); 后綴“”重載為類的成員函數類名(); 前綴“”重載為類的成員函數類名(); 后綴“”重載為類的成員函數類名(類名&); 前綴“”重載為類的友元函數類名(類名&,); 后綴“”重載為類的友元函數類名(類名&); 前綴“”重載為類的友元函數類名(類名&,); 后綴“”重載為類的友元函數類名(類名&); 前綴“”重載為普通函數類名(類名&,); 后綴“”重載為普通函數類名(類名&); 前綴“”重載為普通函數類名(類名&,); 后綴“”重載為普通函數894.3.2重載自增1運算符“”和自減1運算符“”這兩個運例4.11重載自增1運算符“”和自減1運算符“”示例。
{:數據成員 ; 數據值:公有函數 (n=0):(n){} 構造函數 (n){=n;} 設置數據值 (){;} 返回數據值 (){();} 前綴“ (i){();} 后綴 () 前綴 {();} };(,i) 重載后綴為普通函數{ =a; 用暫存a a=(()-1); a的值減1 ; 返回a原來的值,也就是} …… 90例4.11重載自增1運算符“”和自減1運算符“”示例。39例4.11重載自增1運算符“”和自減1運算符“”示例?!?) 主函數(){ i,j; 定義整型對象 (6); 設置數據值 j=; 對i作前綴自增1運算等價于() <<()<<","<<()<<; 輸出數據值7,7 (6); 設置數據值 j=; 對i作后綴自增1運算等價于(0) <<()<<","<<()<<; 輸出數據值7,6 (6); 設置數據值 j=; 對i作前綴自減1運算等價于(i) <<()<<","<<()<<; 輸出數據值5,5 (6); 設置數據值 j=; 對i作后綴自減1運算等價于(i,0) <<()<<","<<()<<; 輸出數據值5,6 (""); 輸出系統提示信息 0; 返回值0,返回操作系統}91例4.11重載自增1運算符“”和自減1運算符“”示例。40*4.3.3重載下標運算符“[]”下標運算符“[]”一般用于在數組中標識數組元素的位置,在語言中,下標運算符“[]”是沒有越界檢查功能的??梢酝ㄟ^重載下標運算符“[]”實現一種更安全、功能更強的數組類型下標運算符的使用方式是a[i],第一個操作數為數組名,重載后就為用戶自定義對象,因此規定重載下標運算符“[]”只能重載為類的成員函數。定義下標運算符“[]”的函數重載的一般聲明格式如下:返回值類型[]();92*4.3.3重載下標運算符“[]”下標運算符“[]”一例4.12重載下標運算符“[]”示例。聲明數組類模板<>
{:數據成員 *; 存儲數據元素值 ; 數組元素個數:公有函數 ():(){=[];} 構造函數 (){;} 析構函數 [](i) 下標運算符"[]"重載為成員函數 { (i<0i>=) { <<"元素位置錯!"<<; (1); 退出程序的運行,返回到操作系統 } [i]; 返回[i] }};……9
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 積極心理與職業幸福感提升計劃
- 供應鏈優化計劃
- 美術班級文化建設活動計劃
- 2024年陜西師范大學輔導員考試真題
- 2025年軟考設計師考試知識點試題及答案
- 2025屆遼寧省撫順市望花區七下數學期末教學質量檢測模擬試題含解析
- 軟考網絡管理員知識分享會試題及答案
- 少兒美術啟蒙課程設置計劃
- 2024年南京郵電大學輔導員考試真題
- 2024年南海成人學院輔導員考試真題
- 經濟學論文的選題與寫作
- 過熱蒸汽壓力控制設計
- 國際志愿服務培訓與實踐-浙江外國語學院中國大學mooc課后章節答案期末考試題庫2023年
- 其他常見疾病的康復
- 技術人員能力考核評分表
- 中國傳統文化知到章節答案智慧樹2023年西安理工大學
- 四位數乘四位數乘法題500道
- 英語閱讀知到章節答案智慧樹2023年北京大學
- 三室兩廳家具、家電采購清單
- 裝配式建筑混凝土結構施工監理實施細則
- 噴涂過程PFMEA分析實例
評論
0/150
提交評論