面向對象程序設計(C++):第8章 多態性_第1頁
面向對象程序設計(C++):第8章 多態性_第2頁
面向對象程序設計(C++):第8章 多態性_第3頁
面向對象程序設計(C++):第8章 多態性_第4頁
面向對象程序設計(C++):第8章 多態性_第5頁
已閱讀5頁,還剩61頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第八章 多態性目錄8.1 多態性概述8.2 運算符重載8.3 虛函數8.4 抽象類8.5 程序實例變步長梯形積分算法求解函數的定積分8.6 綜合實例對個人銀行賬戶管理程序的改進8.7 深度探索8.8 小結28.1 多態性概述多態是指操作接口具有表現多種形態的能力,即能根據操作環境的不同采用不同的處理方式。多態性是面向對象系統的主要特性之一,在這樣的系統中,一組具有相同基本語義的方法能在同一接口下為不同的對象服務。C+語言支持的多態性可以按其實現的時機分為編譯時多態和運行時多態兩類。38.1 多態性概述8.1.1 多態的類型多態的類型重載多態強制多態包含多態參數多態C+不但提供了固有的多態性,還

2、提供了實現自定義多態性的手段。48.1 多態性概述8.1.2 多態的實現多態的種類編譯時的多態運行時的多態綁定是指把一個標識符名和一個存儲地址聯系在一起的過程編譯時的多態綁定工作在編譯連接階段完成的情況稱為靜態綁定。運行時的多態綁定工作在程序運行階段完成的情況稱為動態綁定58.1 多態性概述8.2 運算符重載用“+”、“-”能夠實現復數的加減運算嗎?實現復數加減運算的方法 重載“+”、“-”運算符運算符重載是對已有的運算符賦予多重含義,使同一個運算符作用于不同類型的數據時導致不同的行為。68.2.1 運算符重載的規則C+ 幾乎可以重載全部的運算符,而且只能夠重載C+中已經有的。不能重載的運算符

3、舉例:“.”、“.*”、“:”、“?:”重載之后運算符的優先級和結合性都不會改變。運算符重載是針對新類型數據的實際需要,對原有運算符進行適當的改造。兩種重載方式:重載為類的非靜態成員函數和重載為非成員函數。78.2 運算符重載8.2.2 運算符重載為成員函數聲明形式函數類型 operator 運算符(形參) .重載為類成員函數時 參數個數=原操作數個數-1(后置+、-除外)重載為非成員函數時 參數個數=原操作數個數,且至少應該有一個自定義類型的形參。88.2 運算符重載8.2.2 運算符重載為成員函數(續)雙目運算符 B如果要重載 B 為類成員函數,使之能夠實現表達式 oprd1 B oprd

4、2,其中 oprd1 為A 類對象,則 B 應被重載為 A 類的成員函數,形參類型應該是 oprd2 所屬的類型。經重載后,表達式 oprd1 B oprd2 相當于 oprd1.operator B(oprd2)98.2 運算符重載例8-1復數類加減法運算重載成員函數形式 將“+”、“-”運算重載為復數類的成員函數。 規則:實部和虛部分別相加減。 操作數:兩個操作數都是復數類的對象。108.2 運算符重載 8.2.2 運算符重載為成員函數例8-1(續)#include using namespace std;class Complex /復數類定義public:/外部接口Complex(do

5、uble r = 0.0, double i = 0.0) : real(r), imag(i) /構造函數Complex operator + (const Complex &c2) const;/運算符+重載成員函數Complex operator - (const Complex &c2) const;/運算符-重載成員函數void display() const;/輸出復數private:/私有數據成員double real;/復數實部double imag;/復數虛部;118.2 運算符重載 8.2.2 運算符重載為成員函數例8-1(續)Complex Complex:operato

6、r + (const Complex &c2) const /重載運算符函數實現return Complex(real + c2.real, imag + c2.imag); /創建一個臨時無名對象作為返回值Complex Complex:operator - (const Complex &c2) const /重載運算符函數實現return Complex(real - c2.real, imag - c2.imag); /創建一個臨時無名對象作為返回值void Complex:display() const cout ( real , imag ) endl;128.2 運算符重載 8.

7、2.2 運算符重載為成員函數例8-1(續)int main() /主函數Complex c1(5, 4), c2(2, 10), c3;/定義復數類的對象cout c1 = ; c1.display();cout c2 = ; c2.display();c3 = c1 - c2;/使用重載運算符完成復數減法cout c3 = c1 - c2 = ; c3.display();c3 = c1 + c2;/使用重載運算符完成復數加法cout c3 = c1 + c2 = ; c3.display();return 0;138.2 運算符重載 8.2.2 運算符重載為成員函數例8-1(續)程序輸出的

8、結果為:c1 = (5, 4)c2 = (2, 10)c3 = c1 - c2 = (3, -6)c3 = c1 + c2 = (7, 14)148.2 運算符重載 8.2.2 運算符重載為成員函數運算符成員函數的設計前置單目運算符 U如果要重載 U 為類成員函數,使之能夠實現表達式 U oprd,其中 oprd 為A類對象,則 U 應被重載為 A 類的成員函數,無形參。經重載后,表達式 U oprd 相當于 oprd.operator U()158.2 運算符重載 8.2.2 運算符重載為成員函數運算符成員函數的設計(續)后置單目運算符 +和-如果要重載 +或-為類成員函數,使之能夠實現表達

9、式 oprd+ 或 oprd- ,其中 oprd 為A類對象,則 +或- 應被重載為 A 類的成員函數,且具有一個 int 類型形參。經重載后,表達式 oprd+ 相當于 oprd.operator +(0)168.2 運算符重載 8.2.2 運算符重載為成員函數例8-2 運算符前置+和后置+重載為時鐘類的成員函數。前置單目運算符,重載函數沒有形參,對于后置單目運算符,重載函數需要有一個整型形參。操作數是時鐘類的對象。實現時間增加1秒鐘。178.2 運算符重載 8.2.2 運算符重載為成員函數#include using namespace std;class Clock/時鐘類定義publi

10、c:/外部接口Clock(int hour = 0, int minute = 0, int second = 0);void showTime() const;Clock& operator + ();/前置單目運算符重載Clock operator + (int);/后置單目運算符重載private:/私有數據成員int hour, minute, second;Clock:Clock(int hour/* = 0 */, int minute/* = 0 */, int second/* = 0 */) if (0 = hour & hour 24 & 0 = minute & minu

11、te 60& 0 = second & second hour = hour;this-minute = minute;this-second = second; elsecout Time error! endl;188.2 運算符重載 8.2.2 運算符重載為成員函數例8-2(續)void Clock:showTime() const /顯示時間函數cout hour : minute : second = 60) second -= 60;minute+;if (minute = 60) minute -= 60;hour = (hour + 1) % 24;return *this;C

12、lock Clock:operator + (int) /后置單目運算符重載/注意形參表中的整型參數Clock old = *this;+(*this);/調用前置“+”運算符return old;198.2 運算符重載 8.2.2 運算符重載為成員函數例8-2(續)int main() Clock myClock(23, 59, 59);cout First time output: ;myClock.showTime();cout Show myClock+: ;(myClock+).showTime();cout Show +myClock: ;(+myClock).showTime()

13、;return 0;208.2 運算符重載 8.2.2 運算符重載為成員函數例8-2(續)運行結果:First time output: 23:59:59Show myClock+: 23:59:59Show +myClock: 0:0:18.2.3運算符重載為非成員函數函數的形參代表依自左至右次序排列的各操作數。后置單目運算符 +和-的重載函數,形參列表中要增加一個int,但不必寫形參名。如果在運算符的重載函數中需要操作某類對象的私有成員,可以將此函數聲明為該類的友元。218.2 運算符重載8.2.3運算符重載為非成員函數(續)雙目運算符 B重載后,表達式oprd1 B oprd2 等同于o

14、perator B(oprd1,oprd2 )前置單目運算符 B重載后,表達式 B oprd 等同于operator B(oprd )后置單目運算符 +和-重載后,表達式 oprd B 等同于operator B(oprd,0 )228.2 運算符重載例8-3以非成員函數形式重載Complex的加減法運算和“”運算符將+、-(雙目)重載為非成員函數,并將其聲明為復數類的友元,兩個操作數都是復數類的常引用。將(雙目)重載為非成員函數,并將其聲明為復數類的友元,它的左操作數是std:ostream引用,右操作數為復數類的常引用,返回std:ostream引用,用以支持下面形式的輸出:cout a

15、b;該輸出調用的是:operator (operator (cout, a), b);238.2 運算符重載 8.2.3 運算符重載為非成員函數/8_3.cpp#include using namespace std;class Complex /復數類定義public:/外部接口Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) /構造函數friend Complex operator + (const Complex &c1, const Complex &c2);/運算符+重載friend Complex operator

16、 - (const Complex &c1, const Complex &c2);/運算符-重載friend ostream & operator (ostream &out, const Complex &c); /運算符重載private:/私有數據成員double real;/復數實部double imag;/復數虛部;Complex operator + (const Complex &c1, const Complex &c2) /重載運算符函數實現return Complex(c1.real + c2.real, c1.imag + c2.imag); 248.2 運算符重載 8

17、.2.3 運算符重載為非成員函數例8-3(續)Complex operator - (const Complex &c1, const Complex &c2) /重載運算符函數實現return Complex(c1.real - c2.real, c1.imag - c2.imag); ostream & operator (ostream &out, const Complex &c) /重載運算符函數實現out ( c.real , c.imag );return out;int main() /主函數Complex c1(5, 4), c2(2, 10), c3;/定義復數類的對象co

18、ut c1 = c1 endl;cout c2 = c2 endl;c3 = c1 - c2;/使用重載運算符完成復數減法cout c3 = c1 - c2 = c3 endl;c3 = c1 + c2;/使用重載運算符完成復數加法cout c3 = c1 + c2 = c3 endl;return 0;258.2 運算符重載 8.2.3 運算符重載為非成員函數例8-3(續)8.3.1 一般虛函數成員C+中引入了虛函數的機制在派生類中可以對基類中的成員函數進行覆蓋(重定義)。虛函數的聲明Virtual 函數類型 函數名(形參表) 函數體268.3 虛函數例8-4虛函數成員#include us

19、ing namespace std;class Base1 /基類Base1定義public:virtual void display() const;/虛函數;void Base1:display() const cout Base1:display() endl;class Base2:public Base1 /公有派生類Base2定義public:void display() const;/覆蓋基類的虛函數;void Base2:display() const cout Base2:display() endl;278.3 虛函數 8.3.1 一般虛函數成員 class Derived

20、: public Base2 /公有派生類public:void display() const; /覆蓋基類的虛函數;void Derived:display() const cout Derived:display() display();/對象指針-成員名int main() /主函數Base1 base1;/定義Base1類對象Base2 base2;/定義Base2類對象Derived derived;/定義Derived類對象fun(&base1);/用Base1對象的指針調用fun函數fun(&base2);/用Base2對象的指針調用fun函數fun(&derived);/用D

21、erived對象的指針調用fun函數return 0;28例8-4(續)8.3 虛函數 8.3.1 一般虛函數成員 運行結果:Base1:display()Base2:display()Derived:display()8.3.2 虛析構函數為什么需要虛析構函數?可能通過基類指針刪除派生類對象;如果你打算允許其他人通過基類指針調用對象的析構函數(通過delete這樣做是正常的),就需要讓基類的析構函數成為虛函數,否則執行delete的結果是不確定的。298.3 虛函數例8-5 虛析構函數舉例#include using namespace std;class Base public:Base(

22、);Base:Base() cout Base destructor endl; class Derived: public Basepublic:Derived();Derived();308.3 虛函數 8.3.2 虛析構函數private:int *p;Derived:Derived() p = new int(0);Derived:Derived() cout Derived destructor endl;delete p;void fun(Base* b) delete b;int main() Base *b = new Derived();fun(b);return 0;例8-

23、5(續)運行時結果:Base destructor避免上述錯誤的有效方法就是將析構函數聲明為虛函數,運行結果變為:Derived destructorBase destructor318.3 虛函數 8.3.2 虛析構函數8.4.1 純虛函數純虛函數是一個在基類中聲明的虛函數,它在該基類中沒有定義具體的操作內容,要求各派生類根據實際需要定義自己的版本,純虛函數的聲明格式為:virtual 函數類型 函數名(參數表) = 0;帶有純虛函數的類稱為抽象類:class 類名 virtual 類型 函數名(參數表)=0; /純虛函數 .328.4 抽象類8.4.2 抽象類作用抽象類為抽象和設計的目的而

24、聲明,將有關的數據和行為組織在一個繼承層次結構中,保證派生類具有要求的行為。對于暫時無法實現的函數,可以聲明為純虛函數,留給派生類去實現。注意抽象類只能作為基類來使用。不能聲明抽象類的對象。構造函數不能是虛函數,析構函數可以是虛函數。338.4 抽象類例8-6 抽象類舉例/8_6.cpp#include using namespace std;class Base1 /基類Base1定義public:virtual void display() const = 0;/純虛函數;class Base2: public Base1 /公有派生類Base2定義public:void display(

25、) const;/覆蓋基類的虛函數;void Base2:display() const cout Base2:display() endl;348.4 抽象類 8.4.2 抽象類class Derived: public Base2 /公有派生類Derived定義public:void display() const;/覆蓋基類的虛函數;void Derived:display() const cout Derived:display() display();/對象指針-成員名int main() /主函數Base2 base2;/定義Base2類對象Derived derived;/定義D

26、erived類對象fun(&base2);/用Base2對象的指針調用fun函數fun(&derived);/用Derived對象的指針調用fun函數return 0;358.4 抽象類 8.4.2 抽象類例8-6(續)運行結果:Base2:display()Derived:display()8.5 程序實例變步長梯形積分算法求解函數的定積分算法基本原理我們只考慮最簡單的情況,設被積函數是一個一元函數,定積分表達式為:積分表示的意義是一元函數f(x)在區間a到b之間與x軸所夾的面積36y xabxkxk-1hIkf(x)8.5.1 算法基本原理(續)在每個小區間上都用小的梯形面積來近似原函數的

27、積分,當小區間足夠小時,我們就可以得到原來積分的近似值。每個小區間的面積值公式:實際計算中步長h逐次減半,反復利用上述求積公式進行計算,直到所求得的積分結果滿足要求的精度為止。并得到遞推公式:378.5 程序實例變步長梯形積分算法求解函數的定積分8.5.2程序設計分析388.5 程序實例變步長梯形積分算法求解函數的定積分MyFunction + operator()(x : double) : doubleIntegration + operator ()(a : double, b : double, eps : double) : doubleFunction + operator ()(

28、x : double) : doubleTrapz+ Trapz(pf : const F&) + operator ()(a : double, b : double, eps : double) : double-f8.5.3 源程序及說明 例8-7 變步長梯形積分法求解函數的定積分我們求一個測試函數在某給定區間的積分值,對整個程序進行了測試,誤差為eps為10-7。測試函數:整個程序分為三個獨立的文檔,Trapzint.h文件包括類的定義,Trapzint.cpp文件包括類的成員函數實現。文件intmain.cpp是程序的主函數,主函數中定義了函數類Fun和梯形積分類Trapz的對象39

29、8.5 程序實例變步長梯形積分算法求解函數的定積分/Trapzint.h 文件一,類定義class Function /抽象類Function的定義public:virtual double operator () (double x) const = 0;/純虛函數重載運算符()virtual Function() ;class MyFunction: public Function /公有派生類MyFunction定義public:virtual double operator()(double x) const;/覆蓋虛函數;class Integration /抽象類Integrati

30、on定義public:virtual double operator () (double a, double b, double eps) const = 0;virtual Integration() ;40例8-7(續)8.5 程序實例變步長梯形積分算法求解函數的定積分class Trapz: public Integration/公有派生類Trapz定義public:Trapz(const Function &f) : f(f) /構造函數virtual double operator ()(double a, double b,double eps) const;private:co

31、nst Function &f;/私有成員,Function類對象的指針;/Trapzint.cpp 文件二,類實現#include Trapzint.h/包含類的定義頭文件#include double MyFunction:operator () (double x) const /被積函數return log(1.0 + x) / (1.0 + x * x);double Trapz:operator () (double a,double b,double eps) const /積分運算過程,重載為運算符()bool done = false;/是Trapz類的虛函數成員int n

32、= 1;double h = b - a;double tn = h * (f(a) + f(b) / 2;/計算n = 1時的積分值double t2n;41例8-7(續)8.5 程序實例變步長梯形積分算法求解函數的定積分do double sum = 0;for(int k = 0; k n; k+) double x = a + (k + 0.5) * h;sum += f(x);t2n = (tn + h * sum) / 2.0;/變步長梯形法計算if (fabs(t2n - tn) eps)done = true;/判斷積分誤差else /進行下一步計算tn = t2n;n *=

33、2;h /= 2; while (!done);return t2n;42例8-7(續)8.5 程序實例變步長梯形積分算法求解函數的定積分/8_7.cpp 文件三,主函數#include Trapzint.h/類定義頭文件#include #include using namespace std;int main() /主函數MyFunction f;/定義MyFunction類的對象Trapz trapz(f);/定義Trapz類的對象/計算并輸出積分結果cout TRAPZ Int: setprecision(7) trapz(0, 2, 1e-7) endl;return 0;43例8-

34、7(續)8.5 程序實例變步長梯形積分算法求解函數的定積分運行結果:TRAPZ Int: 0.55489528.6 綜合實例對個人銀行賬戶管理程序的改進本例在第七章例7-10的基礎上,對Account類做了如下改進:(1) 將show函數聲明為虛函數,因此通過指向CreditAccount類實例的Accout類型的指針來調用show函數時,被實際調用的將是為CreditAccount類定義的show函數,這樣,如果創建一個Account指針類型的數組,使各個元素分別指向各個賬戶對象,就可以通過一個循環來調用它們的show函數;(2) 在Account類中添加deposit、withdraw、s

35、ettle這3個函數的聲明,且將它們都聲明為純虛函數,這使得通過基類的指針可以調用派生類的相應函數,而且無需給出它們在基類中的實現。經過這一改動之后,Account類就變成了抽象類。4445-acc : Accumulator-rate : doubleSavingsAccount+SavingsAccount(date : Date, id : int, rate : double) +getRate() : double+deposit(date : Date, amount : double, desc : string)+withdraw(date : Date, amount : d

36、ouble, desc : string)+settle(date : Date)11-acc : Accumulator-credit : double-rate : double-fee : doubleCreditAccount -getDebt() : double+CreditAccount(date : Date, id : int, credit : double, rate : double, fee : double) +getCredit() : double +getRate() : double +getFee() : double +getAvailableCredi

37、t() : double+deposit(date : Date, amount : double, desc : string)+withdraw(date : Date, amount : double, desc : string)+settle(date : Date) +show()-year : int-month : int-day : int-totalDays : int+Date(year : int, month : int, day : int) +getYear() : int +getMonth() : int +getDay() : int + getMaxDay

38、() : int + isLeapYear() : bool + show() + operator - (date : Date) : intDate-lastDate : Date-value : double-sum : double+Accumulator(date : Date, value : double) +getSum(date : Date) : double+change(date : Date, value : double)+reset(date : Date, value : double)Accumulator#Account(date : Date, id :

39、int)#record(date: Date, amount : double, desc : string) # error (msg : string) +getId() : int +getBalance() : double + deposit(date : Date, amount : double, desc : string) + withdraw(date : Date, amount : double, desc : string) + settle(date : Date) + show() +getTotal() : doubleAccount-id : string-b

40、alance : double-total : double1/date.h#ifndef _DATE_H_#define _DATE_H_class Date /日期類private:int year;/年int month;/月int day;/日int totalDays;/該日期是從公元元年1月1日開始的第幾天public:Date(int year, int month, int day);/用年、月、日構造日期int getYear() const return year; int getMonth() const return month; int getDay() const

41、return day; int getMaxDay() const;/獲得當月有多少天bool isLeapYear() const /判斷當年是否為閏年return year % 4 = 0 & year % 100 != 0 | year % 400 = 0;void show() const;/輸出當前日期int operator - (const Date& date) const /計算兩個日期之間差多少天return totalDays - date.totalDays;#endif /_DATE_H_468.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)/accumula

42、tor.h#ifndef _ACCUMULATOR_H_#define _ACCUMULATOR_H_#include date.hclass Accumulator /將某個數值按日累加private:Date lastDate;/上次變更數值的時期double value;/數值的當前值double sum;/數值按日累加之和public:double getSum(const Date &date) const return sum + value * (date - lastDate);/該類其它成員函數的原型和實現與例7-10完全相同,不再重復給出;#endif /_ACCUMULA

43、TOR_H_478.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)/account.h#ifndef _ACCOUNT_H_#define _ACCOUNT_H_#include date.h#include accumulator.h#include class Account /賬戶類private:std:string id;/帳號double balance;/余額static double total; /所有賬戶的總金額protected:/供派生類調用的構造函數,id為賬戶Account(const Date &date, const std:string &id);/記

44、錄一筆帳,date為日期,amount為金額,desc為說明void record(const Date &date, double amount, const std:string &desc);/報告錯誤信息void error(const std:string &msg) const;488.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)public:const std:string &getId() const return id; double getBalance() const return balance; static double getTotal() return

45、 total; /存入現金,date為日期,amount為金額,desc為款項說明virtual void deposit(const Date &date, double amount, const std:string &desc) = 0;/取出現金,date為日期,amount為金額,desc為款項說明virtual void withdraw(const Date &date, double amount, const std:string &desc) = 0;/結算(計算利息、年費等),每月結算一次,date為結算日期virtual void settle(const Date

46、&date) = 0;/顯示賬戶信息virtual void show() const;/SavingsAccount和CreditAccount兩個類的定義與例7-10完全相同,不再重復給出 #endif /_ACCOUNT_H_498.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)/account.cpp/僅下面的函數定義與例7-10不同,其它皆相同,不再重復給出void SavingsAccount:settle(const Date &date) if (date.getMonth() = 1) /每年的一月計算一次利息double interest = acc.getSum(

47、date) * rate/ (date - Date(date.getYear() - 1, 1, 1);if (interest != 0)record(date, interest, interest);acc.reset(date, getBalance();/8_8.cpp#include account.h#include using namespace std;int main() Date date(2008, 11, 1);/起始日期/建立幾個賬戶SavingsAccount sa1(date, S3755217, 0.015);SavingsAccount sa2(date,

48、 02342342, 0.015);508.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)CreditAccount ca(date, C5392394, 10000, 0.0005, 50);Account *accounts = &sa1, &sa2, &ca ;const int n = sizeof(accounts) / sizeof(Account*);/賬戶總數cout (d)deposit (w)withdraw (s)show (c)change day (n)next month (e)exit endl;char cmd;do /顯示日期和總金額date.show

49、();cout tTotal: Account:getTotal() ;int index, day;double amount;string desc;cin cmd;switch (cmd) case d:/存入現金cin index amount;getline(cin, desc);accountsindex-deposit(date, amount, desc);break;518.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續) case w:/取出現金cin index amount;getline(cin, desc);accountsindex-withdraw(dat

50、e, amount, desc);break; case s:/查詢各賬戶信息for (int i = 0; i n; i+) cout i show();cout day;if (day date.getDay()cout date.getMaxDay()cout Invalid day;elsedate = Date(date.getYear(), date.getMonth(), day);break;528.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續) case n:/進入下個月if (date.getMonth() = 12)date = Date(date.getYear

51、() + 1, 1, 1);elsedate = Date(date.getYear(), date.getMonth() + 1, 1);for (int i = 0; i settle(date);break; while (cmd != e);return 0;538.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)2008-11-1 #S3755217 created2008-11-1 #02342342 created2008-11-1 #C5392394 created(d)deposit (w)withdraw (s)show (c)change day (n)next m

52、onth (e)exit2008-11-1 Total: 0 command c 52008-11-5 Total: 0 command d 0 5000 salary2008-11-5 #S3755217 5000 5000 salary2008-11-5 Total: 5000 command c 152008-11-15 Total: 5000 command w 2 2000 buy a cell2008-11-15 #C5392394 -2000 -2000 buy a cell2008-11-15 Total: 3000 command c 252008-11-25 Total:

53、3000 command d 1 10000 sell stock 03232008-11-25 #02342342 10000 10000 sell stock 03232008-11-25 Total: 13000 command n2008-12-1 #C5392394 -16 -2016 interest2008-12-1 Total: 12984 command d 2 2016 repay the credit2008-12-1 #C5392394 2016 0 repay the credit2008-12-1 Total: 15000 command c 52008-12-5

54、Total: 15000 command d 0 5500 salary2008-12-5 #S3755217 5500 10500 salary2008-12-5 Total: 20500 command n2009-1-1 #S3755217 17.77 10517.8 interest2009-1-1 #02342342 15.16 10015.2 interest2009-1-1 #C5392394 -50 -50 annual fee2009-1-1 Total: 20482.9 command s0 S3755217 Balance: 10517.81 02342342 Balan

55、ce: 10015.22 C5392394 Balance: -50 Available credit:99502009-1-1 Total: 20482.9 command e548.6 綜合實例對個人銀行賬戶管理程序的改進例8-8(續)運行結果8.7 深度探索558.7.1 多態類型與非多態類型多態類型與非多態類型有虛函數的類類型稱為多態類型其它類型皆為非多態類型二者的差異語言層面的差異多態類型支持運行時類型識別多態類型對象占用額外的空間設計原則上的差異568.7 深度探索設計原則多態類型多態類型的析構函數一般應為虛函數非多態類型非多態類型不宜作為公共基類由于沒有利用動態多態性,一般可以用

56、組合,而無需用共有繼承;如果繼承,則由于析構函數不是虛函數,刪除對象時所執行操作與指針類型有關,易引起混亂。把不需被繼承的類型設定為非多態類型由于成員函數都是靜態綁定,調用速度較快;對象占用空間較小。578.7 深度探索 8.7.1 多態類型與非多態類型8.7.2 運行時類型識別運行時類型識別允許在運行時通過基類指針(或引用)辨別對象所屬的具體派生類;只對多態類型適用;比虛函數動態綁定的開銷更大,因此應僅對虛函數無法解決的問題使用。運行時類型識別的方式用dynamic_cast做類型轉換的嘗試;用typeid直接獲取類型信息。588.7 深度探索使用dynamic_cast語法形式dynami

57、c_cast(表達式)功能將基類指針轉換為派生類指針,將基類引用轉換為派生類引用;轉換是有條件的如果指針(或引用)所指對象的實際類型與轉換的目的類型兼容,則轉換成功進行;否則如執行的是指針類型的轉換,則得到空指針;如執行的是引用類型的轉換,則拋出異常。598.7 深度探索 8.7.2 運行時類型識別例8-9 dynamic_cast用法示例#include using namespace std;class Base public:virtual void fun1() cout Base:fun1() endl; virtual Base() ;class Derived1: public Base public:virtual void fun1() cout Derived1:fun1() endl; virtual void fun2() cout Derived1:fun2() endl; ;class Derived2: public Derived1 public:virtual void fun1() cout Derived2:

溫馨提示

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

評論

0/150

提交評論