版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
面向對象編程技術與方法(C++)
第4章類與對象第4章類與對象第4章
類與對象
4.1類與對象的定義
4.1.1類的定義
4.1.2類對象
4.1.3類的封裝性和信息隱藏
4.2構造函數與析構函數
4.2.1構造函數
4.2.2析構函數
4.2.3構造與析構的順序
4.3賦值成員函數
4.4靜態(tài)成員
4.4.1靜態(tài)數據成員
4.4.2靜態(tài)成員函數
4.5常成員
4.5.1常數據成員
4.5.2常成員函數
4.5.3mutable 4.6指向成員的指針
4.6.1成員指針的定義與使用
4.6.2如何得到成員函數的地址
4.7組合類
4.8友元
4.8.1友元函數
4.8.2友元類
4.9小結
第4章類與對象4.1類與對象的定義
4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.1類與對象的定義4.1.1類的定義定義一個類,實際上就是定義一種新的數據類型。類把數據和操作封裝在一起,其中的數據成員和成員函數統(tǒng)稱為類的成員。在定義類時還要對類中的某些成員進行隱藏,因此類不僅具有封裝性,還具有信息隱藏性。class類名{public:公有的數據成員和成員函數;protected:受保護的數據成員和成員函數;private:私有的數據成員和成員函數;};//此處的分號不能少!public、private以及protected是訪問屬性關鍵字,它們控制外界訪問類成員的權限。成員的默認訪問屬性為private。一般成員函數和本類的友元函數可以訪問本類的所有成員。公有成員為類與外界交互的接口,一般將成員函數聲明為類的公有成員。外界可以訪問類對象的公有成員。私有成員是類中被隱藏的部分,一般將數據成員定義為類的私有成員。外界不能訪問類的私有成員。受保護成員具有和私有成員相似的訪問屬性,但繼承的情況下,基類受保護成員在派生類中的訪問屬性與私有成員有所不同,將在第6章介紹。第4章類與對象classCPoint{public: intXcoord(){returnX;}//成員函數定義
intYcoord(){returnY;}//成員函數定義
voidSetPoint(intx,inty){X=x;Y=y;} voidMove(intdx,intdy){X+=dx;Y+=dy;}private: intX,Y;//數據成員};//此處分號不能少!第4章類與對象成員函數的函數體部分可以在類內,也可以在類外。當成員函數的定義放在類體外時,必須在類體內對函數進行聲明,類外定義時應在函數名前加上類名和作用域限定符“::”。第4章類與對象一般成員函數可以重載,參數可以帶有默認值。但是析構函數不帶參數,不能重載。類體內定義的成員函數默認為inline函數。類體外定義的成員函數默認情況下不是inline,但可以聲明它為inline,只需在函數聲明以及函數定義的開始加上關鍵字inline即可。注意這時應將定義類和定義成員函數的源代碼放在同一個文件中,否則編譯時在函數調用處無法進行代碼置換。第4章類與對象第4章類與對象第4章類與對象4.1類與對象的定義4.1.2類對象類對象的創(chuàng)建形式和基本數據類型對象一樣。例如:inta1,a2,a[3]; //int對象a1、a2和數組aint*pi=&a1; //指向int對象的指針int&ar=a1; //int對象a1的一個引用arCPointc1,c2,c[3]; //CPoint型CPoint*pc=&c1; //指向CPoint對象的指針CPoint&cr=c1; //CPoint型對象c1的引用1.類對象的定義第4章類與對象4.1.2類對象類代表了某類對象的共同特征,類對象是類的實例(instance)。每個對象分別擁有自己的一套數據成員和成員函數??梢酝ㄟ^對象名(使用運算符“.”)或指向對象的指針(使用運算符“->”)來訪問對象的成員。類的所有非靜態(tài)成員函數都有隱含一個this指針參數。當建立類對象時,this就自動被初始化指向該對象??梢远x指向數據成員和成員函數的指針,4.6節(jié)介紹。2.如何訪問類對象的成員運行結果:d1.X=2,d1.Y=3第4章類與對象4.1.2類對象每個對象所占用的存儲空間只是該對象數據部分所占用的存儲空間,而不包括函數代碼部分。同類成員函數的代碼在內存中只有一份拷貝。但是調用一個對象的成員函數與調用另一個對象的相同成員函數,傳遞的參數和執(zhí)行的結果是不一樣的。3.類對象的存儲第4章類與對象4.1類與對象的定義4.1.3類的封裝性和信息隱藏把數據和操作數據的算法封裝在一起。外界只能通過公有接口實現對數據的訪問,而不能直接訪問私有的數據,這就起到了信息隱藏的作用。將類的接口與實現分離。對于類的用戶來說,只需要知道類的接口、而不需要知道類的實現細節(jié),這樣既保證了程序的安全,又保護了開發(fā)者的權益。參見例4-3。教材中的例子大都比較短小,多數情況下將所有代碼都放在一個cpp文件中。第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數
4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.2構造函數與析構函數4.2.1構造函數1.構造函數的定義與作用2.帶參數的構造函數3.成員初始化列表4.構造函數的重載5.帶默認參數值的構造函數6.拷貝構造函數7.轉換構造函數第4章類與對象4.2.1構造函數1.構造函數的定義與作用當建立類的對象時,構造函數自動被調用。構造函數的名字與類的名字相同,不帶返回類型(注意不是void)。用戶可以根據初始化的要求設計構造函數的參數和函數體。帶構造函數的CPoint類定義參見例4-4,作用是建立類對象時對兩個int數據成員X和Y初始化。第4章類與對象構造函數的主要功能是初始化數據成員,函數體內也可以有其他功能的語句,但最好不含與初始化無關的操作,以保持程序的清晰。構造函數也可以定義在類體外,其函數名前同樣要加上“類名::”。任何一個類都必須含有構造函數,如果類的設計者沒有定義構造函數,則系統(tǒng)會自動生成一個不帶參數的構造函數,它只負責創(chuàng)建對象,而不做初始化工作。第4章類與對象第4章類與對象4.2.1構造函數2.帶參數的構造函數帶參數的構造函數,可以將不同的實參數值傳遞給構造函數,從而實現不同的初始化。在建立對象時給出實參值,在自動調用構造函數的同時將實參值傳遞給構造函數,參數值傳遞的順序與一般函數一樣是從左到右。第4章類與對象第4章類與對象4.2.1構造函數3.構造函數的成員初始化列表前面是在構造函數的函數體內對數據成員賦初值,也可以在成員初始化列表中初始化,有的數據成員則要求必須在列表中初始化。如CPoint構造函數的定義可寫為:
CPoint(intx,inty):X(x),Y(y){} 調用構造函數時先執(zhí)行成員初始化列表,再按順序執(zhí)行花括號內的語句。數據成員在初始化列表中的初始化順序,與它們在類中的聲明順序有關,而與在初始化列表中給出的順序無關。如果構造函數在類體外定義,則初始化列表在函數定義中給出。第4章類與對象第4章類與對象4.2.1構造函數4.構造函數的重載構造函數可以被重載,以提供類對象的不同初始化方法。創(chuàng)建類對象時,如果找不到相匹配的構造函數,那么就不能建立相應的對象。第4章類與對象4.2.1構造函數5.帶默認參數值的構造函數函數重載增加了源代碼量??梢允褂脦J參數值的構造函數:
CPoint(intx=0,inty=0){X=x;Y=y;}構造函數參數傳遞時,順序是從左到右。如果給出了實參值,則對應的數據成員采用實參值作為初值,否則采用默認參數值作為初值。如果構造函數在類體之外定義,那么應該在類內聲明構造函數時為參數指定默認值。一般要避免同時使用帶默認參數值的構造函數和重載構造函數,否則容易出現歧義性問題。第4章類與對象第4章類與對象4.2.1構造函數6.復制構造函數有時我們希望像基本數據類型那樣,利用已有的類對象去初始化新創(chuàng)建的類對象。例如:inta1=0; inta2(a1); CPointobj1; CPointobj2(obj1); 類對象的這種初始化方式是通過調用復制初始化構造函數(簡稱復制或拷貝構造函數)實現的。每一個類都必須含有復制構造函數,如果設計人員沒有顯性定義,編譯器會自動生成一個默認的復制構造函數。復制構造函數也是構造函數,它的形參類型是類類型的引用,這樣在參數傳遞時就不用建立新的類對象,而只是對實參的引用。為了保證不修改被引用的對象,通常把引用參數聲明為const。運行結果:d1.X=4,d1.Y=5d2.X=4,d2.Y=5第4章類與對象在函數參數值傳遞(參數為類類型)、函數值返回(返回類類型)時也會調用拷貝構造函數。有時利用系統(tǒng)自動生成的拷貝構造函數可以滿足要求,但有時需要自己定義,具體我們后面會遇到。第4章類與對象4.2.1構造函數7.轉換構造函數利用轉換構造函數可以將指定的數據類型轉換為當前的類類型。例如由int轉換為CPoint。轉換構造函數實際上是帶默認參數值的構造函數。如果構造函數的參數從第2個開始都帶有默認值,那么它就可以將第1個參數的類型自動轉換為當前的類類型。假設定義構造函數:
CPoint::CPoint(intr){X=r;Y=0;}那么語句“CPoint(5);”的功能是:調用轉換構造函數將5轉換為CPoint類型。本質上是建立一個類對象,數據成員初值分別為5和0。調用轉換構造函數時,要建立一個匿名的臨時對象,該對象使用完畢后被自動刪除。對類型轉換運算符“()”進行重載,可以實現將類類型轉換為其他類型。具體見下一章內容。轉換構造函數和類型轉換運算符,都是在需要時由系統(tǒng)自動調用。注意4.2.1節(jié)幾種構造函數形式,是指構造函數的不同重載形式。在建立類對象需要調用構造函數時,系統(tǒng)會根據情況調用其中的一個。第4章類與對象第4章類與對象4.2.2析構函數析構函數的作用從內存中刪除類對象。析構函數的名字是類名前加符號“~”。析構函數不帶參數,不能重載,也沒有返回類型。其定義形式如下:
Cpoint::~CPoint(){…} 每一個類都必須有析構函數,如果設計者沒有定義,則系統(tǒng)會自動生成一個默認的析構函數,函數體內為空。析構函數由系統(tǒng)自動調用,用戶不能隨意調用。classStudent{public: Student() //構造函數定義
{ number=200801; name=newchar[20]; //申請堆空間
}
~Student(){deletename;}//析構函數定義private: longintnumber; char*name; //指針型數據成員};第4章類與對象第4章類與對象4.2.3構造與析構的順序在同樣的作用域內,調用構造函數建立類對象的順序是誰的定義在前誰先建立;而調用析構函數刪除類對象的順序與構造的順序正好相反。調用函數進行參數傳遞時,會建立局部的參數對象,雖然參數信息傳遞的順序是從左向右,但參數對象建立的順序是從右向左。當全局對象、靜態(tài)局部對象、一般局部對象都存在的情況下,自動析構順序一般是:先刪除一般局部對象,其次是靜態(tài)局部對象,最后刪除全局對象。用new建立的堆對象,只能通過delete刪除。函數內定義的非靜態(tài)對象,當這個函數被調用結束時刪除。第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數
4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.3賦值成員函數復制構造函數的作用是:利用已有類對象去初始化新建的類對象。我們也希望類對象能夠像基本數據類型的變量那樣可以相互賦值。例如:inta1=0,a2=0; a2=a1; CPointobj1,obj2; obj2=obj1; 類對象的這種賦值方式是通過重載賦值運算符函數operator=()實現的,該運算符必須重載為類的成員,簡稱賦值函數。每一個類都必須含有賦值函數,如果設計人員沒有顯性定義,編譯器會自動生成一個。賦值函數的返回類型和形參類型是類類型的引用,為了保證不修改被引用的對象,通常把引用參數聲明為const。例如:CPoint&CPoint::operator=(constCPoint&ref){ X=ref.X; //用被引用對象的X值修改當前對象的X Y=ref.Y; //用被引用對象的Y值修改當前對象的Y Return*this; //返回當前對象}賦值函數和復制構造函數的實現非常相似。不同的是,賦值函數返回*this,以符合賦值的本來含義。復制構造函數用于對象的初始化,而賦值函數用于修改類對象的值。第4章類與對象一旦定義了賦值函數,就可以像基本數據類型對象那樣使用賦值符號“=”。例如:CPointobj1,obj2,obj3;//建立三個類對象obj3=obj2=obj1; 上面的賦值操作,實際上是把obj1作為實參,先調用對象obj2的賦值函數即
“obj2.operator=(obj1);”,然后把返回值作為實參,再調用對象obj3的賦值函數。參見例4-13。第4章類與對象有時用戶必須自己定義拷貝構造函數和賦值函數,例如類中包含指向動態(tài)分配內存的指針成員的情況。classA{public: A(intr){p=newint(r);} //初始化p指向int對象 ~A(){deletep;} //釋放p所指的內存空間private:
int*p; //指針型數據成員}; 執(zhí)行下面的一段語句,雖然可以通過編譯連接,但程序運行時會出現問題。Aa(5);//建立A類的對象aAb(a);//建立對象b,復制構造函數Ac(5),d(10);//建立兩個A類對象d=c;//調用賦值函數第4章類與對象前面利用默認復制構造函數和默認賦值函數,造成同一段內存被釋放兩次,或者造成內存資源泄漏。解決辦法:第4章類與對象第4章類與對象Aa(5);//建立A類的對象aAb(a);//建立對象b,復制構造函數Ac(5),d(10);//建立兩個A類對象d=c;//調用賦值函數第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員
4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.4靜態(tài)成員一般地說,如果定義n個同類的對象,那么每個對象的數據成員各自有值,互不相關。有時需要某些數據成員在同類的多個對象之間可以共享,這可以通過定義靜態(tài)數據成員實現。4.4.1靜態(tài)數據成員classCPoint{public: CPoint(intx=0,inty=0){X=x
;Y=y
;}private: intX,Y; //一般數據成員
static
intcount;//靜態(tài)數據成員};intCPoint::count=0;//初始化靜態(tài)數據成員count一般數據成員是在類對象建立時分配空間,在對象刪除時釋放空間。而靜態(tài)數據成員是在程序編譯時分配空間,到程序結束時釋放空間。靜態(tài)數據成員在所有對象之外單獨存放,而不占用對象的存儲空間。盡管靜態(tài)數據成員的存儲具有全局性,但其作用域僅限于所屬類的范圍。與普通的數據成員是一樣,靜態(tài)數據成員也有public、private、protected之分。在類外不能訪問private、protected的靜態(tài)數據成員,可以訪問public的靜態(tài)數據成員,訪問時可以用“類名::”進行限制,或通過類對象訪問。第4章類與對象注意事項:第4章類與對象4.4靜態(tài)成員成員函數也可以聲明為靜態(tài)的,方法是在類內成員函數聲明或定義的前面冠以static關鍵字。類外定義時不需要帶static。靜態(tài)成員函數主要用來訪問類的靜態(tài)成員,不能直接訪問類的非靜態(tài)成員。靜態(tài)成員函數沒有this指針。與靜態(tài)數據成員一樣,類外調用public靜態(tài)成員函數時,可以用“類名::”進行限制,或通過類對象訪問。4.4.2靜態(tài)成員函數運行結果:223,4,2第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員
4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.5常成員常數據成員的聲明格式如下:
const
數據類型數據成員名;const數據成員必須在構造函數的成員初始化列表中初始化。對象建立以后,其const數據成員的值就不再改變。如果類中包含引用型數據成員和其他類類型的數據成員,其初始化工作也必須在初始化列表中進行。列表中對成員的初始化順序,與它們在列表中的順序無關,而與它們在類中的聲明順序有關。包含這類數據成員的類定義也就不能使用默認構造函數。4.5.1常數據成員第4章類與對象4.5常成員const成員函數聲明格式如下: 返回類型成員函數名(參數列表)const;//const必須有如果const成員函數定義在類體外,則不論是類內聲明還是類外定義,都不能省略關鍵字const。const成員函數不能修改任何數據成員的值,但可以使用它們。const成員函數不能調用同類的非const成員函數,但可以調用同類的const成員函數。如果聲明一個類對象為const,則類外只能調用該對象的公有const成員函數。4.5.2常成員函數運行結果:2,2,2,82,2,2,85,5,2,8第4章類與對象4.5常成員如果定義類時聲明一個數據成員是mutable,如mutableinta;則表示其值是可以改變的。這時即使是const成員函數,也可以修改mutable數據成員的值。mutable不常用。4.5.3mutable第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針
4.7組合類 4.8友元 4.9小結
第4章類與對象4.6指向成員的指針可以通過指向成員的指針(簡稱為成員指針),來訪問類對象的成員。C++專門為成員指針準備了三個運算符:“::*”用于聲明成員指針,而“->*”和“.*”用來通過成員指針訪問對象的成員,注意這三個運算符中間不能有空格。參見例4-18。4.6.1成員指針的定義與使用第4章類與對象4.6指向成員的指針一般我們得不到成員函數的地址。雖然外部函數的函數名就代表函數的入口地址,但成員函數不是。由于每個成員函數的類型都是一個獨有的特殊類型,無法轉換到任何其它類型,因此利用成員函數指針也得不到成員函數的地址。如果非要得到成員函數的地址不可,可以使用union類型來逃避C++的類型轉換檢測。參見例4-19。4.6.2如何得到成員函數的地址第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類
4.8友元 4.9小結
第4章類與對象4.7組合類新類中包含有已經定義的其他類類型的數據成員,我們稱該新類型為組合類。const數據成員、引用型數據成員、類類型數據成員的初始化操作必須在組合類構造函數(包括拷貝構造函數等各種重載形式)的成員初始化列表中進行。有時組合類構造函數的成員初始化列表中,并沒有明顯給出內部類成員的構造函數,這時調用默認構造函數。調用析構函數的順序與調用構造函數的順序相反。第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元
4.9小結
第4章類與對象4.8友元可以通過關鍵字friend聲明一個外部函數為類的友元函數,從而使該函數可以訪問類的所有成員。4.8.1友元函數第4章類與對象注意一個類的友元函數雖然可以訪問該類的成員,但并不是該類的成員函數。聲明友元函數時也就不受private、protected和public的限制。同一個函數可以聲明為多個類的友元。參見例4-23。也可以把另一個類的成員函數聲明為友元函數:第4章類與對象4.8友元也可以通過關鍵字friend聲明某個類為另一個類的友元。友元類的每個成員函數都可以訪問另一個類中的所有成員。如果類B是類A的友元,則要求類B必須在類A之前進行聲明或者定義。4.8.2友元類運行結果:1,23,4ThenumberofCPointobjects:3第4章類與對象4.1類與對象的定義 4.2構造函數與析構函數 4.3賦值成員函數 4.4靜態(tài)成員 4.5常成員 4.6指向成員的指針 4.7組合類 4.8友元 4.9小結
第4章類與對象4.9小結類將不同類型的數據和對數據的操作封裝成一個整體。類是抽象的,類對象是具體的。數據成員體現類的屬性,成員函數體現類的行為。類成員由private、proteced、public決定其訪問屬性。public成員是類對象和外界聯系的接口。構造函數在創(chuàng)建和初始化對象時自動調用。析構函數在對象作用域結束時自動調用。構造函數可以重載,而析構函數沒有參數,不能重載。復制構造函數的作用是利用已有的對象去初始化新建對象。賦值函數的作用是將一個已有對象的值賦給另一個已有對象。第4章類與對象靜態(tài)數據成員和靜態(tài)成員函數是依賴于類的,與是否建立對象無關。const成員函數只能使用數據成員,但不能修改它們的值;const成員函數不能調用另一個非const成員函數。如果定義了一個const對象,則只能調用其中的const成員函數。只能通過構造函數的成員初始化列表對const數據成員、引用型數據成員和類成員進行初始化。類的友元可以訪問該類的所有成員,但友元不是該類的成員。友元類的所有成員函數都是友元函數。THANKS面向對象編程技術與方法(C++)
第5章運算符重載第5章運算符重載第5章
運算符重載
5.1運算符重載的概念
5.2運算符重載的規(guī)則
5.3運算符重載的兩種形式
5.3.1重載為類的成員函數
5.3.2重載為類的友元函數
5.3.3兩種重載方式討論
5.4特殊運算符重載舉例
5.4.1類型轉換運算符
5.4.2復合賦值運算符
5.4.3自增和自減運算符
5.4.4流提取運算符和流插入運算符
5.5函數對象
5.6小結
第5章運算符重載5.1運算符重載的概念
5.2運算符重載的規(guī)則 5.3運算符重載的兩種形式 5.4特殊運算符重載舉例 5.5函數對象 5.6小結
第5章運算符重載5.1運算符重載的概念運算符重載也就是函數重載。運算符函數重載的聲明格式: 返回類型operator運算符(形參列表);C++預定義的運算符只能操作基本數據類型的對象,例如對于int型對象a和b,求和可以直接寫為a+b。但是對于類對象,不能直接使用類似的表達方式。例如,對于兩個CPoint類型的對象obj1和obj2,我們仍然希望能夠像基本數據類型那樣將表達式寫為:obj1+obj2。解決方法就是在定義類CPoint時,重載運算符函數operator+()。第5章運算符重載5.1運算符重載的概念 5.2運算符重載的規(guī)則
5.3運算符重載的兩種形式 5.4特殊運算符重載舉例 5.5函數對象 5.6小結
第5章運算符重載5.2運算符重載的規(guī)則大多數C++運算符都可以重載。下面幾個不能重載:成員訪問運算符(.)、成員指針訪問運算符(.*)、作用域運算符(::)、求字節(jié)數運算符(sizeof)、類型識別(typeid)、條件運算符(?:)C++不允許用戶定義新的運算符,只可以對已有的運算符進行重載。重載不會改變運算符操作對象的個數。重載后運算符的優(yōu)先級以及結合性不變。運算符重載函數與一般函數的區(qū)別是:前者的參數個數只能是一個或者兩個,而一般函數參數的個數沒有限制。運算符重載函數的形參不能帶默認值。雖然重載允許改變函數的功能,但應當使運算符重載后的功能與重載前的功能類似。一般來說,操作數包含有類對象的運算符都應該重載。但取地址運算符“&”可以直接使用,不用自己重載;賦值運算符“=”有時不用重載,因為系統(tǒng)可以提供一個默認的賦值函數,特殊情況下則需要用戶重新定義。第5章運算符重載5.1運算符重載的概念 5.2運算符重載的規(guī)則 5.3運算符重載的兩種形式5.4特殊運算符重載舉例 5.5函數對象 5.6小結
第5章運算符重載5.3運算符重載的兩種形式5.3.1重載為類的成員函數在下面的例子中,定義一個復數類Complex。以一元運算符取負(-)和二元運算符減(-)為例,說明將一元運算符和二元運算符重載為成員函數的方法。由于類的非靜態(tài)成員函數都隱含一個this參數,當調用對象的成員函數時this被自動初始化指向當前的對象。因此表面上看,一元運算符成員函數不帶參數,二元運算符成員函數帶一個參數,該參數是右操作數(運算符右側的操作數),左操作數由this提供。第5章運算符重載5.3.2重載為類的友元函數將上例改為重載為友元的形式。由于友元函數不是類的成員函數,因此沒有this指針。這時,一元運算符友元函數應帶一個參數,二元運算符友元函數應帶兩個參數。第5章運算符重載5.3.3兩種重載方式討論運算符的兩種重載形式都可以實現要求的功能,但是成員函數和友元函數是不同的。從表面上看,友元函數比成員函數多一個形參。實際上,成員函數所在的對象就是第1個操作數。一般而言,應將一元運算符重載為成員函數,將二元運算符重載為友元函數?!?)”、“[]”、“->”、“->*”及“=”必須重載為成員函數。如果運算符的第一個操作數為當前的類類型,則可以重載為成員函數;如果運算符有一個操作數不是當前的類類型,則應重載為友元函數。例如,要計算(7.53-c1)的值,其中c1是Complex類對象。成員函數重載時,該表達式被解釋為:7.53.operator-(c1);友元函數重載時,該表達式被解釋為:operator-(Complex(7.53),c1)第5章運算符重載第5章運算符重載5.1運算符重載的概念 5.2運算符重載的規(guī)則 5.3運算符重載的兩種形式 5.4特殊運算符重載舉例
5.5函數對象 5.6小結
第5章運算符重載5.4特殊運算符重載舉例5.4.1類型轉換運算符5.4.2復合賦值運算符5.4.3自增和自減運算符5.4.4流提取運算符和流插入運算符第5章運算符重載5.4特殊運算符重載舉例5.4.1類型轉換運算符類的轉換構造函數可以將數據由其他類型轉換為當前的類類型。反過來,如果想將數據由當前的類類型轉換為其他類型,需要將類型轉換運算符“()”重載為類的成員函數。其聲明形式為:
類名::operatorT();
該語句聲明將數據由當前的類類型轉換為T類型。注意該成員函數沒有參數,沒有返回類型,但函數體內必須有返回T類型值的語句。第5章運算符重載5.4特殊運算符重載舉例5.4.1類型轉換運算符5.4.2復合賦值運算符5.4.3自增和自減運算符5.4.4流提取運算符和流插入運算符第5章運算符重載5.4特殊運算符重載舉例5.4.2復合賦值運算符第4章介紹了賦值運算符的重載方法。假設在類定義中,重載了賦值運算符“=”和加法運算符“+”,那么復合賦值運算符“+=”是不是就可以直接使用呢?答案是否定的。要想使“+=”適用于類對象,必須單獨進行重載。其他復合賦值運算符也一樣。第5章運算符重載5.4特殊運算符重載舉例5.4.1類型轉換運算符5.4.2復合賦值運算符5.4.3自增和自減運算符5.4.4流提取運算符和流插入運算符第5章運算符重載5.4特殊運算符重載舉例5.4.3自增和自減運算符自增“++”和自減“--”都有前置和后置兩種情況。如果有“inta=3;”,++a的含義是“a的值先加1再被使用”,a++的含義是“先使用a的原值然后a再加1”。重載”++”后應保持原來的含義不變。規(guī)定后置一元運算符重載為成員函數時,帶一個int型參數,該參數并不使用,只是為了和前置情況區(qū)分開。前置++與后置++重載為成員函數的聲明形式分別為:
const類名&類名::operator++(); //前置
const類名類名::operator++(int);//后置運行結果:a:11c:11b:11c:10第5章運算符重載5.4特殊運算符重載舉例5.4.1類型轉換運算符5.4.2復合賦值運算符5.4.3自增和自減運算符5.4.4流提取運算符和流插入運算符第5章運算符重載5.4特殊運算符重載舉例5.4.4流提取和流插入運算符在標準庫的istream類中重載了提取運算符(>>),ostream類中重載了插入運算符(<<),這兩個運算符重載函數可以完成從istream對象(cin)提取和向ostream對象插入基本類型數據的功能,但不能提取和插入類對象數值。如果希望能夠提取和插入類對象數值,需要在定義類時重載這兩個運算符。第5章運算符重載5.1運算符重載的概念 5.2運算符重載的規(guī)則 5.3運算符重載的兩種形式 5.4特殊運算符重載舉例 5.5函數對象
5.6小結
第5章運算符重載5.5函數對象函數對象是指重載了調用運算符“()”(注意與類型轉換運算符區(qū)分開)的普通類對象,但是可以采用與函數調用形式相同的寫法來調用對象的該運算符重載函數。函數對象可以代替函數指針作為參數。優(yōu)點:首先,函數對象可以保存上次調用結果的數據,而使用普通函數只能將結果存儲在全局或者靜態(tài)變量中;其次,編譯器能內嵌重載的運算符代碼,就避免了函數調用所產生的運行時問題。運行結果:5,7第5章運算符重載5.1運算符重載的概念 5.2運算符重載的規(guī)則 5.3運算符重載的兩種形式 5.4特殊運算符重載舉例 5.5函數對象 5.6小結
第5章運算符重載5.6小結運算符重載可以使我們用一種簡潔的方式表達類對象的運算。C++的大部分運算符都可以進行重載。重載后運算符原有的優(yōu)先級、結合性和所需的操作數個數不變。運算符“=”、“()”、“[]”、“->”及“->*”必須重載為成員函數,一元運算符和復合賦值運算符一般重載為成員函數,其他二元運算符一般重載為友元函數。函數對象是指重載了調用運算符“()”的普通類對象。THANKS面向對象編程技術與方法(C++)
第6章繼承與派生第6章繼承與派生第6章
繼承與派生
6.1基類與派生類
6.2對基類成員的訪問控制
6.2.1公有繼承
6.2.2私有繼承
6.2.3保護繼承
6.3派生類的構造函數與析構函數
6.3.1構造函數
6.3.2析構函數
6.4組合與繼承的選擇
6.5多繼承中的歧義
6.6虛基類
6.7小結
第6章繼承與派生6.1基類與派生類
6.2對基類成員的訪問控制6.3派生類的構造函數與析構函數 6.4組合與繼承的選擇 6.5多繼承中的歧義 6.6虛基類 6.7小結
第6章繼承與派生6.1基類與派生類繼承是面向對象程序設計的基本特征之一。下面結合大學人員的例子介紹基類、派生類、派生、繼承、繼承方式、單繼承、多繼承、多重繼承等概念。Student是在UnivPerson的基礎上產生出的新類。UnivPerson稱為Student的基類(或父類),Student稱為UnivPerson的派生類(或子類)。Student繼承了UnivPerson的幾乎所有成員(構造函數、析構函數、賦值函數除外),并增加了新成員。這種從已有類產生新類的過程就是類的派生,從另一個角度看,從已有類獲得屬性和行為的過程就是類的繼承。繼承實現了對基類代碼的重用。派生類只有一個直接基類的情況稱為單繼承,派生類具有多個直接基類的情況稱為多繼承。一個派生類同樣可以作為基類,繼續(xù)派生出新的類,例如在Student基礎上派生graduate類。第6章繼承與派生第6章繼承與派生6.1基類與派生類 6.2對基類成員的訪問控制 6.3派生類的構造函數與析構函數 6.4組合與繼承的選擇 6.5多繼承中的歧義 6.6虛基類 6.7小結
第6章繼承與派生6.2對基類成員的訪問控制基類成員在派生類中的訪問屬性,不僅與它們在基類中的訪問屬性有關,還與繼承方式有關。6.2.1公有繼承1.公有繼承的特點當派生類以public方式繼承基類時,基類的public和protected成員在派生類中的訪問屬性不變,即仍為public或protected,派生類新增加的成員函數可以訪問它們,但外界只可以調用派生類對象的public成員。關于基類的private成員,派生類內的成員函數不能直接訪問。第6章繼承與派生2.同名屏蔽現象調用派生類對象的成員函數時,如果派生類沒有定義該函數,則從基類中尋找相匹配的函數,包括函數名稱、返回類型、參數列表、是否帶const等都要考慮。如果派生中類重新定義(Redefining)了同名函數,則編譯時基類中的所有同名函數都將被屏蔽。這時,如果想調用基類中的同名函數,可以通過“基類名::”進行限制。運行結果:Base::f()Derived2::f()Base::f()Derived4::f()第6章繼承與派生3.向上類型轉換通過公有繼承,派生類就具備了基類的功能,在需要基類對象的地方,可以用派生類對象來代替。這時存在從派生類向基類的自動轉換,稱為向上類型轉換(upcasting),或稱為類型適應。這種類型轉換可能在下面情況下發(fā)生:(1)用派生類對象賦值或初始化基類對象(2)用派生類對象初始化基類引用(3)將派生類對象的地址賦給指向基類的指針由于存在向上類型轉換,在這幾種情況下,一般只能訪問基類的成員。向上類型轉換時,派生類對象中的新增成員將被舍棄,只將從基類繼承來的部分賦給基類對象。這種現象稱為對象切割(objectslicing)。向上類型轉換是自動進行的。注意向下類型轉換是不能自動進行的,即不能自動由基類轉換為派生類。第6章繼承與派生6.2.2私有繼承當派生類以private方式繼承基類時,基類的public和protected成員在派生類中的訪問屬性均變?yōu)閜rivate,那么派生類新增加的成員函數可以訪問它們,但是外界不能訪問它們。關于基類的private成員,派生類內的成員函數都不能直接訪問。第6章繼承與派生6.2.2保護繼承當派生類以protected繼承基類時,基類的public和protected成員在派生類中的訪問屬性均變?yōu)閜rotected,即派生類新增成員函數可以訪問它們,但外界不能訪問?;惖膒rivate成員,派生類內都不能直接訪問。在直接派生類中,私有繼承和保護繼承的作用相同:在類外不能訪問任何基類成員,而派生類的成員函數可以訪問基類的public和protected成員。但如果繼續(xù)派生,就有所不同。如果再以公有方式派生出新類,原來私有繼承的基類成員在派生類中都不可訪問,原來保護繼承的基類public和protected成員在派生類中具有protected訪問屬性,可被新類的成員函數訪問。關于三種繼承方式下基類成員在直接派生類中的訪問屬性,可以總結如表所示。第6章繼承與派生第6章繼承與派生6.1基類與派生類 6.2對基類成員的訪問控制 6.3派生類的構造函數與析構函數
6.4組合與繼承的選擇 6.5多繼承中的歧義 6.6虛基類 6.7小結
第6章繼承與派生6.3.1構造函數由于派生類不能繼承基類的構造函數,因此對繼承過來的基類數據成員的初始化工作,將由派生類的構造函數來完成。在設計派生類的構造函數時,不僅要考慮派生類新增數據成員的初始化,還要考慮基類數據成員的初始化。由于派生類的const數據成員、引用型數據成員、類類型成員的初始化操作也在構造函數的初始化列表中進行。初始化列表中的執(zhí)行順序是:首先調用基類的構造函數(多個基類的初始化順序與繼承的順序有關),然后才是派生類的成員初始化(順序與類內的聲明順序有關)。6.3派生類的構造函數與析構函數第6章繼承與派生6.3.2析構函數派生類不能繼承基類的析構函數,如果需要析構的話,就要在派生類中定義自己的析構函數。上例沒有顯性定義析構函數,實際上是利用了編譯系統(tǒng)自動生成的析構函數。析構的順序與構造的順序相反。在上例基礎上,添加析構函數,參見例6-4。6.3派生類的構造函數與析構函數第6章繼承與派生6.1基類與派生類 6.2對基類成員的訪問控制 6.3派生類的構造函數與析構函數 6.4組合與繼承的選擇
6.5多繼承中的歧義 6.6虛基類 6.7小結
第6章繼承與派生可以看出無論是組合還是繼承,結果都是把子對象放在新類型對象中,都在新類型的構造函數初始化列表中構造這些子對象。那么編程時到底應該選用那種方法呢?當新類型需要的不是已有類的接口,而是使用已有類的功能,這時應該采用組合。例如鳥與翅膀的關系,這是一種has-a的關系。當新類型需要的是已有類的接口,這時應該用繼承。例如鳥與動物的關系,這是一種is-a的關系。6.4組合與繼
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 同軸電纜安裝方法、接頭接法
- 電梯門關閉速度與安全檢測考核試卷
- 機車車輛驅動電機性能分析考核試卷
- 藥品零售行業(yè)法規(guī)動態(tài)分析-洞察分析
- 幼兒教師自我鑒定范文
- 工程進度獎罰措施
- 患者跌倒、墜床等意外事件的防范制度、措施、報告制度、處置預案、工作流程
- 一年級下冊數學復習計劃
- 依賴關系在機器學習中的應用-洞察分析
- 2023-2024學年四川省樂山市高二上學期期末考試生物試題(解析版)
- 組織學與胚胎學課程教學大綱
- 網絡傳播概論(第5版) 課件 第一章 網絡媒介的演變
- 2023-2024學年江西省鷹潭市余江區(qū)八年級(上)期末數學試卷(含解析)
- 2023北京西城六年級(上)期末英語試卷含答案
- 珠海金灣區(qū)2023-2024學年七年級上學期期末數學達標卷(含答案)
- 京東五力模型分析報告
- XX學校2024年校長務虛會講話稿范文
- 大學英語四級考試模擬試卷(附答案)
- 廣西壯族自治區(qū)欽州市浦北縣2023-2024學年七年級上學期期末歷史試題
- 法律英語 何家弘編 第四版課文翻譯(1-20課)
- 高級會計師 案例分析第五章 企業(yè)成本管理
評論
0/150
提交評論