上麵的例子中,在派生類構造函數Rectangle(int,int,int,int)的原型中不能包括成員初始化表。

二、對派生類構造函數的進一步討論

1.構造函數的執行順序

如果派生類與基類同時定義有構造函數,當編譯器創建派生類對象時,首先執行基類的構造函數,然後再執行派生類構造函數。

由輸出結果可以看出,程序首先執行基類的構造函數,然後才執行派生類構造函數。析構函數的執行順序恰好與構造函數的執行順序相反。當派生類與基類同時定義有析構函數時,編譯器會先執行派生類的析構函數,然後再執行基類的析構函數。

2.調用基類的構造函數必須是已定義的

派生類成員初始化表中調用的基類構造函數必須是基類中已定義的構造函數,否則會出錯。

因為基類Location中並無帶一個參數的構造函數。

3.省略基類的構造函數

如果在派生類構造函數的成員初始化表中,省略了基類的構造函數,那麼該基類必須擁有缺省構造函數,或根本沒有定義任何構造函數,否則會出錯。

如果我們沒有為派生類定義任何構造函數,那麼該派生類的基類必須擁有缺省構造函數。原因很簡單,派生類定義任何構造函數,編譯器會為該派生類自動生成一個缺省構造函數,該缺省構造函數的成員初始化表為空,這意味著創建派生類對象時,必須調用基類的缺省構造函數。

4.派生類中包含對象成員

這時,既要為基類構造函數指定一個成員初始化表,也要為對象成員指定一個成員初始化表。

構造函數執行順序為:

(1)基類構造函數

(2)對象成員構造函數

(3)派生類構造函數

當派生類和基類有相同名字的成員時,由於繼承的關係,派生類中一共有兩份同名的成員,此時編譯器會調用哪一份數成員?讓我們來看一個例子。

在本例中,派生類和基類有相同名字的數據成員value和成員函數show()。當我們在函數main()中執行語句ob.show();

時,由於ob是派生類對象,所以編譯器調用派生類的成員函數show()。由輸出結果可以看到,將屬於派生類的數據成員valude顯示到屏幕上。

當派生類中定義了與基類中相同名字的數據成員或成員函數時,基類中同名的成員便被隱藏起來,使得編譯器在派生類的作用域內“看不見”基中的同名的成員。這種現象叫成員覆蓋。

值得注意的是,所謂塞類中同名的成員被隱藏起來,並不表示這些繼承來的成員消失了,它們仍被繼承下來且是派生類成員的一部分,隻是為了避免混播,,編譯器才將其隱藏起來。使用作用域分辨符調用繼承來的基類中的shem()函數。

覆蓋函數是指派生類中重新定義一基類中已存在的成員函數,該函數除了必須有相同的函數名稱之外,其函數的參數表與返回值都可以不同於基類中同名稱的函數。當編譯器發現派生類中定義了與基類中成員函數同名的函數時,便將基類中同名的成員函數隱藏起來,而不理會覆蓋函數的參數表與返回值是否相同。

編譯器調用覆蓋函數時,根據作用域的原則來決定調用哪一函數。

重載函數是指在同一有效的作用域內,兩函數的名字必須相同,返回值也可以相同,但參數表必須可以相互區分。

編譯器調用重載函數時,根據參數表的不同來決定調用哪一個函數。

從作用域的角度很容易理解覆蓋函數和重栽函數的區別。在上麵的例子中,覆蓋函數show()處於兩個不同的作用域,它們的全名可以理解為:

Parent::show()和Child::show()

因此,它們實際上是不同名的函數,自然不是重載函數。

一般情況下,最好不要使用覆蓋函數,需要時,可以使用虛函數,這將在下一章介紹。

8.6舉例

例8.17類Point記錄一個點的坐標,類Line描述的是直線的概念。類Line是類Point公有派生類,直線的起點坐標由類Point給出。

在本例中,類Line是公有派生類,但類line的成員函數仍然不可訪問基類Point中的私有成員,因此,Show()函數隻能通過基類Point的成員函數GetX()和GetY()來獲取起點坐標值。

對該程序有如下說明:

1.類Chemistry是類ComFinal公有派生類,所以在派生類的成員函數Show()中可以訪問基類的保護成員。

2.在派生類中定義了與基類的成員函數同名的Show()函數,該函數是一個覆蓋函數。當我們通過派生類的對象訪問Show()函數時,基類的同名函數Show()就會隱藏起來。

3.我們可以將派生類的對象賦值給基類的對象,還可以將派生類的對象的地址賦值給基類的對象的指針。這樣,我們通過基類的對象或指針訪問Show()函數時,將調用基類的函數Show()

4.本例的要點在於:

保護成員

覆蓋函數

派生類與基類的相互轉換

成員初始化的作用

練習題

1.繼承的基本概念是什麼?

2.什麼是公有派生類?什麼是私有派生類?它們之間有什麼不同?

3.在繼承關係下,什麼是不可訪問成員?

4.什麼是保護成員?在公有派生類中,基類的保護成員的訪問權限有何變化?

5.什麼是成員覆蓋?覆蓋函數與重載函數有什麼不同?

6.在派生類中如何為基類進行初始化?

7.在公有派生類中,派生類與基類之間如何進行轉換?

8.類Person用於描述“人”的概念,數據成員hame、sex和iage分別記錄姓名、性別和年齡。類Address是類Person的公有派生,用來記錄一個人的地址信息,數據成員piv-ince,city和street分別記錄省、市、街道的名字,zip記錄郵政編碼。我們自S來完成這兩個類的定義,並設計一個測試程序。