面向?qū)ο蟪绦蛟O(shè)計(jì)(C++):第8章 多態(tài)性_第1頁
面向?qū)ο蟪绦蛟O(shè)計(jì)(C++):第8章 多態(tài)性_第2頁
面向?qū)ο蟪绦蛟O(shè)計(jì)(C++):第8章 多態(tài)性_第3頁
面向?qū)ο蟪绦蛟O(shè)計(jì)(C++):第8章 多態(tài)性_第4頁
面向?qū)ο蟪绦蛟O(shè)計(jì)(C++):第8章 多態(tài)性_第5頁
已閱讀5頁,還剩61頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、第八章 多態(tài)性目錄8.1 多態(tài)性概述8.2 運(yùn)算符重載8.3 虛函數(shù)8.4 抽象類8.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分8.6 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)8.7 深度探索8.8 小結(jié)28.1 多態(tài)性概述多態(tài)是指操作接口具有表現(xiàn)多種形態(tài)的能力,即能根據(jù)操作環(huán)境的不同采用不同的處理方式。多態(tài)性是面向?qū)ο笙到y(tǒng)的主要特性之一,在這樣的系統(tǒng)中,一組具有相同基本語義的方法能在同一接口下為不同的對象服務(wù)。C+語言支持的多態(tài)性可以按其實(shí)現(xiàn)的時機(jī)分為編譯時多態(tài)和運(yùn)行時多態(tài)兩類。38.1 多態(tài)性概述8.1.1 多態(tài)的類型多態(tài)的類型重載多態(tài)強(qiáng)制多態(tài)包含多態(tài)參數(shù)多態(tài)C+不但提供了固有的多態(tài)性,還

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

3、舉例:“.”、“.*”、“:”、“?:”重載之后運(yùn)算符的優(yōu)先級和結(jié)合性都不會改變。運(yùn)算符重載是針對新類型數(shù)據(jù)的實(shí)際需要,對原有運(yùn)算符進(jìn)行適當(dāng)?shù)母脑?。兩種重載方式:重載為類的非靜態(tài)成員函數(shù)和重載為非成員函數(shù)。78.2 運(yùn)算符重載8.2.2 運(yùn)算符重載為成員函數(shù)聲明形式函數(shù)類型 operator 運(yùn)算符(形參) .重載為類成員函數(shù)時 參數(shù)個數(shù)=原操作數(shù)個數(shù)-1(后置+、-除外)重載為非成員函數(shù)時 參數(shù)個數(shù)=原操作數(shù)個數(shù),且至少應(yīng)該有一個自定義類型的形參。88.2 運(yùn)算符重載8.2.2 運(yùn)算符重載為成員函數(shù)(續(xù))雙目運(yùn)算符 B如果要重載 B 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 oprd1 B oprd

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

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

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

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

8、結(jié)果為:c1 = (5, 4)c2 = (2, 10)c3 = c1 - c2 = (3, -6)c3 = c1 + c2 = (7, 14)148.2 運(yùn)算符重載 8.2.2 運(yùn)算符重載為成員函數(shù)運(yùn)算符成員函數(shù)的設(shè)計(jì)前置單目運(yùn)算符 U如果要重載 U 為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)式 U oprd,其中 oprd 為A類對象,則 U 應(yīng)被重載為 A 類的成員函數(shù),無形參。經(jīng)重載后,表達(dá)式 U oprd 相當(dāng)于 oprd.operator U()158.2 運(yùn)算符重載 8.2.2 運(yùn)算符重載為成員函數(shù)運(yùn)算符成員函數(shù)的設(shè)計(jì)(續(xù))后置單目運(yùn)算符 +和-如果要重載 +或-為類成員函數(shù),使之能夠?qū)崿F(xiàn)表達(dá)

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

10、c:/外部接口Clock(int hour = 0, int minute = 0, int second = 0);void showTime() const;Clock& operator + ();/前置單目運(yùn)算符重載Clock operator + (int);/后置單目運(yùn)算符重載private:/私有數(shù)據(jù)成員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 運(yùn)算符重載 8.2.2 運(yùn)算符重載為成員函數(shù)例8-2(續(xù))void Clock:showTime() const /顯示時間函數(shù)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) /后置單目運(yùn)算符重載/注意形參表中的整型參數(shù)Clock old = *this;+(*this);/調(diào)用前置“+”運(yùn)算符return old;198.2 運(yùn)算符重載 8.2.2 運(yùn)算符重載為成員函數(shù)例8-2(續(xù))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 運(yùn)算符重載 8.2.2 運(yùn)算符重載為成員函數(shù)例8-2(續(xù))運(yùn)行結(jié)果:First time output: 23:59:59Show myClock+: 23:59:59Show +myClock: 0:0:18.2.3運(yùn)算符重載為非成員函數(shù)函數(shù)的形參代表依自左至右次序排列的各操作數(shù)。后置單目運(yùn)算符 +和-的重載函數(shù),形參列表中要增加一個int,但不必寫形參名。如果在運(yùn)算符的重載函數(shù)中需要操作某類對象的私有成員,可以將此函數(shù)聲明為該類的友元。218.2 運(yùn)算符重載8.2.3運(yùn)算符重載為非成員函數(shù)(續(xù))雙目運(yùn)算符 B重載后,表達(dá)式oprd1 B oprd2 等同于o

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

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

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

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

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

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

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

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

22、);Base:Base() cout Base destructor endl; class Derived: public Basepublic:Derived();Derived();308.3 虛函數(shù) 8.3.2 虛析構(gòu)函數(shù)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(續(xù))運(yùn)行時結(jié)果:Base destructor避免上述錯誤的有效方法就是將析構(gòu)函數(shù)聲明為虛函數(shù),運(yùn)行結(jié)果變?yōu)椋篋erived destructorBase destructor318.3 虛函數(shù) 8.3.2 虛析構(gòu)函數(shù)8.4.1 純虛函數(shù)純虛函數(shù)是一個在基類中聲明的虛函數(shù),它在該基類中沒有定義具體的操作內(nèi)容,要求各派生類根據(jù)實(shí)際需要定義自己的版本,純虛函數(shù)的聲明格式為:virtual 函數(shù)類型 函數(shù)名(參數(shù)表) = 0;帶有純虛函數(shù)的類稱為抽象類:class 類名 virtual 類型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù) .328.4 抽象類8.4.2 抽象類作用抽象類為抽象和設(shè)計(jì)的目的而

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

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

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

27、積分,當(dāng)小區(qū)間足夠小時,我們就可以得到原來積分的近似值。每個小區(qū)間的面積值公式:實(shí)際計(jì)算中步長h逐次減半,反復(fù)利用上述求積公式進(jìn)行計(jì)算,直到所求得的積分結(jié)果滿足要求的精度為止。并得到遞推公式:378.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分8.5.2程序設(shè)計(jì)分析388.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分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 變步長梯形積分法求解函數(shù)的定積分我們求一個測試函數(shù)在某給定區(qū)間的積分值,對整個程序進(jìn)行了測試,誤差為eps為10-7。測試函數(shù):整個程序分為三個獨(dú)立的文檔,Trapzint.h文件包括類的定義,Trapzint.cpp文件包括類的成員函數(shù)實(shí)現(xiàn)。文件intmain.cpp是程序的主函數(shù),主函數(shù)中定義了函數(shù)類Fun和梯形積分類Trapz的對象39

29、8.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分/Trapzint.h 文件一,類定義class Function /抽象類Function的定義public:virtual double operator () (double x) const = 0;/純虛函數(shù)重載運(yùn)算符()virtual Function() ;class MyFunction: public Function /公有派生類MyFunction定義public:virtual double operator()(double x) const;/覆蓋虛函數(shù);class Integration /抽象類Integrati

30、on定義public:virtual double operator () (double a, double b, double eps) const = 0;virtual Integration() ;40例8-7(續(xù))8.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分class Trapz: public Integration/公有派生類Trapz定義public:Trapz(const Function &f) : f(f) /構(gòu)造函數(shù)virtual double operator ()(double a, double b,double eps) const;private:co

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

32、= 1;double h = b - a;double tn = h * (f(a) + f(b) / 2;/計(jì)算n = 1時的積分值double t2n;41例8-7(續(xù))8.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分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;/變步長梯形法計(jì)算if (fabs(t2n - tn) eps)done = true;/判斷積分誤差else /進(jìn)行下一步計(jì)算tn = t2n;n *=

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

34、7(續(xù))8.5 程序?qū)嵗儾介L梯形積分算法求解函數(shù)的定積分運(yùn)行結(jié)果:TRAPZ Int: 0.55489528.6 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)本例在第七章例7-10的基礎(chǔ)上,對Account類做了如下改進(jìn):(1) 將show函數(shù)聲明為虛函數(shù),因此通過指向CreditAccount類實(shí)例的Accout類型的指針來調(diào)用show函數(shù)時,被實(shí)際調(diào)用的將是為CreditAccount類定義的show函數(shù),這樣,如果創(chuàng)建一個Account指針類型的數(shù)組,使各個元素分別指向各個賬戶對象,就可以通過一個循環(huán)來調(diào)用它們的show函數(shù);(2) 在Account類中添加deposit、withdraw、s

35、ettle這3個函數(shù)的聲明,且將它們都聲明為純虛函數(shù),這使得通過基類的指針可以調(diào)用派生類的相應(yīng)函數(shù),而且無需給出它們在基類中的實(shí)現(xiàn)。經(jīng)過這一改動之后,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);/用年、月、日構(gòu)造日期int getYear() const return year; int getMonth() const return month; int getDay() const

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

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

43、TOR_H_478.6 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù))/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:/供派生類調(diào)用的構(gòu)造函數(shù),id為賬戶Account(const Date &date, const std:string &id);/記

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

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

46、&date) = 0;/顯示賬戶信息virtual void show() const;/SavingsAccount和CreditAccount兩個類的定義與例7-10完全相同,不再重復(fù)給出 #endif /_ACCOUNT_H_498.6 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù))/account.cpp/僅下面的函數(shù)定義與例7-10不同,其它皆相同,不再重復(fù)給出void SavingsAccount:settle(const Date &date) if (date.getMonth() = 1) /每年的一月計(jì)算一次利息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 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù))CreditAccount ca(date, C5392394, 10000, 0.0005, 50);Account *accounts = &sa1, &sa2, &ca ;const int n = sizeof(accounts) / sizeof(Account*);/賬戶總數(shù)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:/存入現(xiàn)金cin index amount;getline(cin, desc);accountsindex-deposit(date, amount, desc);break;518.6 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù)) case w:/取出現(xiàn)金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 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù)) case n:/進(jì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 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù))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 綜合實(shí)例對個人銀行賬戶管理程序的改進(jìn)例8-8(續(xù))運(yùn)行結(jié)果8.7 深度探索558.7.1 多態(tài)類型與非多態(tài)類型多態(tài)類型與非多態(tài)類型有虛函數(shù)的類類型稱為多態(tài)類型其它類型皆為非多態(tài)類型二者的差異語言層面的差異多態(tài)類型支持運(yùn)行時類型識別多態(tài)類型對象占用額外的空間設(shè)計(jì)原則上的差異568.7 深度探索設(shè)計(jì)原則多態(tài)類型多態(tài)類型的析構(gòu)函數(shù)一般應(yīng)為虛函數(shù)非多態(tài)類型非多態(tài)類型不宜作為公共基類由于沒有利用動態(tài)多態(tài)性,一般可以用

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

57、c_cast(表達(dá)式)功能將基類指針轉(zhuǎn)換為派生類指針,將基類引用轉(zhuǎn)換為派生類引用;轉(zhuǎn)換是有條件的如果指針(或引用)所指對象的實(shí)際類型與轉(zhuǎn)換的目的類型兼容,則轉(zhuǎn)換成功進(jìn)行;否則如執(zhí)行的是指針類型的轉(zhuǎn)換,則得到空指針;如執(zhí)行的是引用類型的轉(zhuǎn)換,則拋出異常。598.7 深度探索 8.7.2 運(yùn)行時類型識別例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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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

提交評論