第6章《C++程序設(shè)計教程與實驗指導(dǎo)》-楊國興多態(tài)性.ppt_第1頁
第6章《C++程序設(shè)計教程與實驗指導(dǎo)》-楊國興多態(tài)性.ppt_第2頁
第6章《C++程序設(shè)計教程與實驗指導(dǎo)》-楊國興多態(tài)性.ppt_第3頁
第6章《C++程序設(shè)計教程與實驗指導(dǎo)》-楊國興多態(tài)性.ppt_第4頁
第6章《C++程序設(shè)計教程與實驗指導(dǎo)》-楊國興多態(tài)性.ppt_第5頁
已閱讀5頁,還剩41頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、C+語言程序設(shè)計,楊國興 張東玲 彭濤,中國水利水電出版社,第6章 多態(tài)性,6.1 運(yùn)算符重載 6.2 運(yùn)算符重載為類的成員函數(shù) 6.3 運(yùn)算符重載為類的友元函數(shù) 6.4 虛函數(shù),6.1 運(yùn)算符重載,6.1.1 問題的提出 例4.3的復(fù)數(shù)類 #include iostream.h class CComplex private: double real; double imag; public: CComplex(double r, double i); void Print(); CComplex Add(CComplex c); CComplex Sub(CComplex c); ;,第6章

2、 多態(tài)性,CComplex CComplex:Add(CComplex c) CComplex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp; CComplex CComplex:Sub(CComplex c) CComplex temp; temp.real = real - c.real; temp.imag = imag - c.imag; return temp; ,6.1 運(yùn)算符重載,6.1.1 問題的提出(續(xù)一) void main(void) CComplex a(1, 2), b(

3、3.0, 4.0), c,d; c = a.Add(b); d = a.Sub(b); cout c = ; c.Print(); cout d = ; d.Print(); ,第6章 多態(tài)性,運(yùn)算符重載:運(yùn)算符重載的實質(zhì)就是對已有的運(yùn)算符賦予多重含義,使同一個運(yùn)算符 作用于不同類型的數(shù)據(jù)時,產(chǎn)生不同的行為。運(yùn)算符重載的實質(zhì)就是函數(shù)重載。,例6.1 用運(yùn)算符實現(xiàn)復(fù)數(shù)的加減運(yùn)算,#include iostream using namespace std; class CComplex private: double real; double imag; public: CComplex(doub

4、le r=0, double i=0); void Print(); CComplex operator +(CComplex c); CComplex operator -(CComplex c); ; CComplex:CComplex (double r, double i) real = r; imag = i; ,第6章 多態(tài)性,例6.1 (續(xù)一),void CComplex:Print() cout ( real , imag ) endl; CComplex CComplex:operator +(CComplex c) CComplex temp; temp.real = re

5、al + c.real; temp.imag = imag + c.imag; return temp; CComplex CComplex:operator -(CComplex c) CComplex temp; temp.real = real - c.real; temp.imag = imag - c.imag; return temp; ,第6章 多態(tài)性,例6.1 (續(xù)二),void main(void) CComplex a(1, 2), b(3.0, 4.0), c,d; c = a+b; d = a-b; cout c = ; c.Print(); cout d = ; d.

6、Print(); ,第6章 多態(tài)性,該語句相當(dāng)于對函數(shù)operator +(CComplex c)的調(diào)用:“c=a.operator +(b)”,實現(xiàn)兩個復(fù)數(shù)的加法運(yùn)算。,程序運(yùn)行結(jié)果為: c = (4, 6) d = (-2, -2),6.1 運(yùn)算符重載,6.1.2 運(yùn)算符重載的格式與規(guī)則 1. 運(yùn)算符重載的格式 運(yùn)算符重載為類的成員函數(shù) 運(yùn)算符重載為類的友元函數(shù) 運(yùn)算符重載的為類的成員函數(shù),在類中聲明的格式為: 函數(shù)類型 operator 運(yùn)算符(參數(shù)表); 定義該函數(shù)的格式: 函數(shù)類型 類名:operator 運(yùn)算符(參數(shù)表) 函數(shù)體; 也可以將重載運(yùn)算符函數(shù)的定義直接寫在類中。,第6章

7、 多態(tài)性,6.1 運(yùn)算符重載,6.1.2 運(yùn)算符重載的格式與規(guī)則(續(xù)) 2. 運(yùn)算符重載的規(guī)則 (1)除“.”、“*”、“:”、“?:”和“sizeof”等幾個運(yùn)算符不能重載外,C+中幾乎所有的運(yùn)算符都可以重載。 (2)運(yùn)算符被重載后,其優(yōu)先級和結(jié)合性不會改變。 (3)不能改變運(yùn)算符操作對象的個數(shù)。,第6章 多態(tài)性,6.2 運(yùn)算符重載為類的成員函數(shù),6.2.1 雙目運(yùn)算符重載 雙目運(yùn)算符,如果重載為類的成員函數(shù),其參數(shù)為一個,即比運(yùn)算對象少一個。 例6.2 復(fù)數(shù)的乘法運(yùn)算,在上例的基礎(chǔ)上添加乘法運(yùn)算符重載函數(shù)。復(fù)數(shù)類乘法運(yùn)算的定義如下: (a+bi)*(x+yi)= a*x-b*y + (a*

8、y + b*x)i,第6章 多態(tài)性,例6.2 復(fù)數(shù)乘法運(yùn)算源程序,#include iostream using namespace std; class CComplex private: double real; double imag; public: CComplex(double r=0, double i=0); void Print(); CComplex operator +(CComplex c); CComplex operator -(CComplex c); CComplex operator *(CComplex c); ; CComplex:CComplex (do

9、uble r, double i) real = r; imag = i; ,第6章 多態(tài)性,例6.2 (續(xù)一),void CComplex:Print() cout ( real , imag ) endl; CComplex CComplex:operator +(CComplex c) CComplex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp; CComplex CComplex:operator -(CComplex c) CComplex temp; temp.real = rea

10、l - c.real; temp.imag = imag - c.imag; return temp; ,第6章 多態(tài)性,例6.2 (續(xù)二),CComplex CComplex:operator *(CComplex c) CComplex temp; temp.real = real * c.real - imag * c.imag; temp.imag = real * c.imag + imag * c.real; return temp; void main(void) CComplex a(1, 2), b(3.0, 4.0), c, d, e, f; c = a+b; d = a-

11、b; e = a*b; f = a+1; cout c = ; c.Print(); cout d = ; d.Print(); cout e = ; e.Print(); cout f = ; f.Print(); ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: c = (4, 6) d = (-2, -2) e = (-5,10) f = (2, 2),總結(jié):設(shè)有雙目運(yùn)算符 B,如果要重載 B 為類的成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd1 B oprd2,其中 oprd1 為A 類對象,則 B 應(yīng)被重載為 A 類的成員函數(shù),形參類型應(yīng)該是 oprd2 所屬的類型。 經(jīng)重載后,表達(dá)式oprd1 B o

12、prd2 相當(dāng)于 oprd1.operator B(oprd2),注意重載雙目運(yùn)算符只需要一個參數(shù)。,6.2 運(yùn)算符重載為類的成員函數(shù),6.2.2 單目運(yùn)算符重載 單目運(yùn)算符,如果重載為類的成員函數(shù),不需要參數(shù)。 為區(qū)分前置和后置運(yùn)算符,C+規(guī)定: 對于前置單目運(yùn)算符,重載函數(shù)沒有參數(shù) 對于后置單目運(yùn)算符,重載函數(shù)有一個整型參數(shù),這個整型參數(shù)沒有其他用途,只是用于區(qū)分前置運(yùn)算與后置運(yùn)算。,第6章 多態(tài)性,例6.3 定義一個CInt類,類中只有一個數(shù)據(jù)成員i,兩個運(yùn)算符“+”的重載函數(shù),一個沒有參數(shù),實現(xiàn)的是前置運(yùn)算符重載,另一個有一個整型參數(shù),實現(xiàn)后置運(yùn)算符重載。,#include iostr

13、eam using namespace std; class CInt private: int i; public: CInt(int a=0); void Print(); CInt operator +(); CInt operator +(int); ; CInt:CInt (int a) i = a; ,第6章 多態(tài)性,void CInt:Print() cout i= i endl; CInt CInt:operator +() CInt temp; temp.i = +i; return temp; CInt CInt:operator +(int) CInt temp; tem

14、p.i = i+; return temp; ,例6.3 (續(xù)),void main(void) CInt a(5), b(5), c, d; c = a+; d = +b; cout a: ; a.Print(); cout b: ; b.Print(); cout c: ; c.Print(); cout d: ; d.Print(); ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: a: i=6 b: i=6 c: i=5 d: i=6,6.2 運(yùn)算符重載為類的成員函數(shù),6.2.3 賦值運(yùn)算符重載 如果類中只包含簡單數(shù)據(jù)類型的數(shù)據(jù)成員,則使用C+提供的賦值運(yùn)算符“=”就可以實現(xiàn)將一個對象賦給另一個對

15、象。如前面復(fù)數(shù)類的對象,就可以將一個對象直接賦給另一個對象。但如果類的數(shù)據(jù)成員比較復(fù)雜(如含有指針),這樣直接賦值就會產(chǎn)生問題,我們必須重載賦值運(yùn)算符“=”才能正確使用“=”。,第6章 多態(tài)性,例6.4 類A只有一個數(shù)據(jù)成員str,是一個字符指針,在構(gòu)造函數(shù)中為str申請存儲空間并賦值,在析構(gòu)函數(shù)中釋放內(nèi)存。,#include iostream #include string using namespace std; class A private: char *str; public: A(char *s=no data); A(); void print(); ; A:A (char *s

16、) int len = strlen(s); str = new charlen+1; strcpy(str,s); ,第6章 多態(tài)性,例6.4 (續(xù)),A:A () if(str) delete str; void A:print() cout str endl; void main(void) A *p = new A(AAAA); A a1; a1=*p; a1.print(); delete p; a1.print(); ,第6章 多態(tài)性,例6.5 帶有重載賦值運(yùn)算符的A類,#include iostream #include string using namespace std; c

17、lass A private: char *str; public: A(char *s=no data); A(); A ,第6章 多態(tài)性,例6.5 (續(xù)一),A:A () if(str) delete str; A ,第6章 多態(tài)性,例6.5 (續(xù)二),void main(void) A *p = new A(AAAA); A a1; a1=*p; a1.print(); delete p; a1.print(); ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: AAAA AAAA,6.3 運(yùn)算符重載為類的友元函數(shù),6.3.1 問題的提出 (1)復(fù)數(shù)與復(fù)數(shù)相加(c1,c2,c3是復(fù)數(shù)類的對象)。 c3

18、=c1+c2; (2)一個復(fù)數(shù)與一個實數(shù)的加法運(yùn)算 c3=c1+10.8; (3)一個實數(shù)與一個復(fù)數(shù)相加就會出現(xiàn)錯誤。 c3= 10.8 + c1; 因為加號左邊的運(yùn)算對象是實數(shù),C+試圖將加號右邊的運(yùn)算對象解釋為實數(shù),但C+無法將一個復(fù)數(shù)轉(zhuǎn)換為一個實數(shù),從而產(chǎn)生錯誤。 將運(yùn)算符重載為友元函數(shù)可以解決這個問題。,第6章 多態(tài)性,6.3 運(yùn)算符重載為類的友元函數(shù),6.3.2 運(yùn)算符重載為友元函數(shù) 類中的聲明: friend 函數(shù)類型 operator 運(yùn)算符(參數(shù)表); 運(yùn)算符重載函數(shù)的定義形式: 函數(shù)類型 operator 運(yùn)算符(參數(shù)表) 函數(shù)體; ,第6章 多態(tài)性,例6.6 用友元函數(shù)實現(xiàn)

19、復(fù)數(shù)類加減運(yùn)算符的重載,#include iostream using namespace std; class CComplex private: double real; double imag; public: CComplex(double r=0, double i=0); void Print(); friend CComplex operator +(CComplex c1,CComplex c2); friend CComplex operator -(CComplex c1,CComplex c2); ; CComplex:CComplex (double r, double

20、 i) real = r; imag = i; ,第6章 多態(tài)性,例6.6 (續(xù)一),void CComplex:Print() cout ( real , imag ) endl; CComplex operator +(CComplex c1, CComplex c2) CComplex temp; temp.real = c1.real + c2.real; temp.imag = c1.imag + c2.imag; return temp; CComplex operator -(CComplex c1, CComplex c2) CComplex temp; temp.real =

21、 c1.real - c2.real; temp.imag = c1.imag - c2.imag; return temp; ,第6章 多態(tài)性,例6.6 (續(xù)二),void main(void) CComplex a(1, 2), b(3.0, 4.0), c, d, e; c = a+b; d = b-10; e = 20+a; cout c = ; c.Print(); cout d = ; d.Print(); cout e = ; e.Print(); ,第6章 多態(tài)性,相當(dāng)于函數(shù)調(diào)用“c=operator+(a, b)”,程序運(yùn)行結(jié)果為: c = (4, 6) d = (-7, 4

22、) e = (21, 2),總結(jié):設(shè)有雙目運(yùn)算符 B,如果要重載 B 為類的友元函數(shù),則該友元函數(shù)也有兩個參數(shù),分別為運(yùn)算符的兩個運(yùn)算對象。重載后,表達(dá)式oprd1 B oprd2 等同于調(diào)用函數(shù)operator B(oprd1,oprd2 )。 單目運(yùn)算符也可以重載為類的友元函數(shù),該友元函數(shù)有一個參數(shù)。,6.4 虛函數(shù),6.4.1 用虛函數(shù)實現(xiàn)動態(tài)多態(tài) 回顧例5.6 void main() CShape *ps3; CShape s(Red); CPoint p1(10,10), p2(100,100),p3(50,50); CLine l(p1,p2,Green); CCircle c(p

23、3, 20, Black); ps0 = ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: Draw a Shape. The color is Red Draw a Shape. The color is Green Draw a Shape. The color is Red Black,為了能通過基類的指針調(diào)用派生類的成員函數(shù),可以使用虛函數(shù)的方法,即把成員函數(shù)Draw()聲明為虛函數(shù)。,例6.7 用虛函數(shù)實現(xiàn)動態(tài)多態(tài),#include #include using namespace std; class CPoint private: int X; int Y; public: CPoint(in

24、t x=0, int y=0) X=x; Y=y; CPoint(CPoint ,第6章 多態(tài)性,例6.7 (續(xù)一),class CShape private: char Color10; public: CShape(char *c) strcpy(Color,c); virtual void Draw() cout Draw a Shape. The color is Color endl; void PrintColor() cout Color endl; ;,第6章 多態(tài)性,例6.7 (續(xù)二),class CLine:public CShape private: CPoint Sta

25、rt; CPoint End; public: CLine(CPoint s, CPoint e, char *c):CShape(c),Start(s),End(e) virtual void Draw() cout Draw a Line from ( Start.GetX() , Start.GetY(); cout ) to ( End.GetX() , End.GetY() ), with color ; PrintColor(); ;,第6章 多態(tài)性,例6.7 (續(xù)三),class CCircle:public CShape private: CPoint Center; int

26、Radius; public: CCircle(CPoint ctr, int r, char *c):CShape(c),Center(ctr) Radius = r; virtual void Draw() cout Draw a Circle at center ( Center.GetX() , ; cout Center.GetY() ) with radius Radius and color ; PrintColor(); ;,第6章 多態(tài)性,例6.7 (續(xù)四),void main() CShape *ps3; CShape s(Red); CPoint p1(10,10), p

27、2(100,100),p3(50,50); CLine l(p1,p2,Green); CCircle c(p3, 20, Black); ps0 = ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: Draw a Shape. The color is Red Draw a Line from (10, 10) to (100, 100) , with color Green Draw a Circle at center (50, 50) with radius 20 and color Black,6.4 虛函數(shù),6.4.1 用虛函數(shù)實現(xiàn)動態(tài)多態(tài)(續(xù)) 總結(jié): (1)將成員函數(shù)聲明為虛函數(shù),在函數(shù)原型

28、前加關(guān)鍵字virtual,如果成員函數(shù)的定義直接寫在類中,也在前面加關(guān)鍵字virtual。 (2)將成員函數(shù)聲明為虛函數(shù)后,再將基類指針指向派生類對象,在程序運(yùn)行時,就會根據(jù)指針指向的具體對象來調(diào)用各自的虛函數(shù),稱之為動態(tài)多態(tài)。 (3)如果基類的成員函數(shù)是虛函數(shù),在其派生類中,原型相同的函數(shù)自動成為虛函數(shù)。,第6章 多態(tài)性,6.4 虛函數(shù),6.4.2 用虛函數(shù)實現(xiàn)動態(tài)多態(tài)的機(jī)制 為了實現(xiàn)動態(tài)多態(tài),編譯器對每個包含虛函數(shù)的類創(chuàng)建一個虛函數(shù)地址表,并設(shè)置一個虛函數(shù)地址指針指向這個對象的虛函數(shù)地址表。使用基類指針對虛函數(shù)調(diào)用時,通過這個虛函數(shù)地址指針,在虛函數(shù)地址表中查找函數(shù)地址。 由于包含虛函數(shù)的

29、類,有一個虛函數(shù)地址指針,與沒有虛函數(shù)的類相比,含有虛函數(shù)類的對象所占用的存儲空間要多一個指針?biāo)加玫膬?nèi)存。,第6章 多態(tài)性,例6.8 含有虛函數(shù)類的對象所占用的存儲空間。,#include using namespace std; class A private: int a; public: virtual void func() ; class B : public A private: int b; public: virtual void func() virtual void func1() ; void main(void) cout sizeof(A)= sizeof(A) e

30、ndl; cout sizeof(B)= sizeof(B) endl; ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: sizeof(A)=8 sizeof(B)=12,6.4 虛函數(shù),6.4.2 用虛函數(shù)實現(xiàn)動態(tài)多態(tài)的機(jī)制(續(xù)) 每個含有虛函數(shù)類的對象都有一個虛函數(shù)地址指針,指向該類虛函數(shù)表,如果用基類的指針調(diào)用虛函數(shù),在編譯時,并不能確定這個指針的具體指向,而是在運(yùn)行時,根據(jù)指針?biāo)赶虻木唧w對象(基類的對象或其派生類的對象),虛函數(shù)地址指針才有一個確定的值,即相應(yīng)類的這個虛函數(shù)的地址。從而實現(xiàn)動態(tài)多態(tài)。,第6章 多態(tài)性,6.4 虛函數(shù),6.4.3 虛析構(gòu)函數(shù) 析構(gòu)函數(shù)也可以定義為虛函數(shù),如果基類的析

31、構(gòu)函數(shù)定義為虛析構(gòu)函數(shù),則派生類的析構(gòu)函數(shù)就會自動成為虛析構(gòu)函數(shù)。 如果基類的指針指向派生類對象,當(dāng)用delete刪除這個對象時,若析構(gòu)函數(shù)不是虛函數(shù),就要調(diào)用基類的析構(gòu)函數(shù),而不會調(diào)用派生類的析構(gòu)函數(shù)。如果為基類和派生類的對象分配了動態(tài)內(nèi)存,或者為派生類的對象成員分配了動態(tài)內(nèi)存,這時釋放的只是基類中動態(tài)分配的內(nèi)存,而派生類中動態(tài)分配的內(nèi)存未被釋放,因此一般應(yīng)將析構(gòu)函數(shù)定義為虛析構(gòu)函數(shù)。,第6章 多態(tài)性,例6.9 定義職員類CEmployee,數(shù)據(jù)成員有姓名(字符指針型數(shù)據(jù))和年齡,由CEmployee類派生出教師類CTeacher,增加數(shù)據(jù)成員教學(xué)簡歷(字符指針型數(shù)據(jù))。,#include

32、#include using namespace std; class CEmployee private: char *name; int age; public: CEmployee(char *n, int a); virtual CEmployee(); ; CEmployee:CEmployee(char *n, int a) name=new charstrlen(n)+ 1 ; strcpy(name, n); age = a; ,第6章 多態(tài)性,例6.9 (續(xù)一),CEmployee:CEmployee() cout Destruct CEmployee endl; if(na

33、me) delete name; class CTeacher : public CEmployee private: char *mainCourse; public: CTeacher(char *n, char *course, int a); virtual CTeacher(); /由于基類已定義虛析構(gòu)函數(shù),此處也可不加virtual ; CTeacher:CTeacher(char *n, char * course, int a) : CEmployee(n,a) mainCourse = new charstrlen(course)+1; strcpy(mainCourse,

34、course); ,第6章 多態(tài)性,例6.9 (續(xù)二),CTeacher:CTeacher() cout Destruct CTeacher endl; if(mainCourse) delete mainCourse; void main(void) CEmployee *p3; p0 = new CEmployee(Name1, 20); p1 = new CTeacher(Name2,C for 2 years,C+ 3 years,26); p2 = new CTeacher(Name3,Data structure for 2 years,C+ 3 years,30); for(in

35、t i=0; i3; i+) delete pi; ,第6章 多態(tài)性,程序運(yùn)行結(jié)果為: Destruct CEmployee Destruct CTeacher Destruct CEmployee Destruct CTeacher Destruct CEmployee,若不定義為虛析構(gòu)函數(shù),程序運(yùn)行結(jié)果為: Destruct CEmployee Destruct CEmployee Destruct CEmployee,由于未調(diào)用CTeacher類析構(gòu)函數(shù),導(dǎo)致成員mainCourse空間未被釋放,6.4 虛函數(shù),6.4.4 純虛函數(shù)與抽象類 純虛函數(shù)是不必定義函數(shù)體的特殊虛函數(shù),純虛函數(shù)的聲明格式為: virtual 函數(shù)類型 函數(shù)名(參數(shù)表)= 0; 含有純虛函數(shù)的類稱為抽象類。抽象類常常用作派生類的基類。 如果派生類繼承了抽象類的純虛函數(shù),卻沒有重新定義原型相同且?guī)Ш瘮?shù)體的虛函數(shù),或者派生類定義了基類所沒有定義的純虛函數(shù),則派生類仍然是抽象類,在多層派生的過程中,如果到某個派生類為止,所有純虛函數(shù)都已全部重新定義,則該派生類就成為非抽象類。 不能定義抽象類的對象,但

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論