C++衍生類別的構成
衍生類別中的成員包括從基類繼承過來的成員和自己增加的成員兩大部分。從基類繼承的成員體現了衍生類別從基類繼承而獲得的共性,而新增加的成員體現了衍生類別的個性。正是這些新增加的成員體現了衍生類別與基類的不同,體現了不同衍生類別之間的區別。
在基類中包括資料成員和成員函數 (或稱資料與方法)兩部分,衍生類別分為兩大部分:一部分是從基類繼承來的成員,另一部分是在聲明衍生類別時增加的部分。每一部分均分別包括資料成員和成員函數。
實際上,並不是把基類的成員和衍生類別自己增加的成員簡單地加在一起就成為衍生類別。構造一個衍生類別包括以下3部分工作。
1) 從基類接收成員
衍生類別把基類全部的成員(不包括建構函式和解構函式)接收過來,也就是說是沒有選擇的,不能選擇接收其中一部分成員,而捨棄另一部分成員。 從定義衍生類別的一般形式中可以看出是不可選擇的。
這樣就可能出現一種情況:有些基類的成員,在衍生類別中是用不到的,但是也必須繼承過來。這就會造成資料的冗餘,尤其是在多次派生之後,會在許多衍生類別對象中存在大量無用的資料,不僅浪費了大量的空間,而且在對象的建立、賦值、複製和參數的傳遞中, 花費了許多無謂的時間,從而降低了效率。這在目前的C++標準中是無法解決的,要求我們根據衍生類別的需要謹慎選擇基類,使冗餘量最小。不要隨意地從已有的類中找一個作為基類去構造衍生類別,應當考慮怎樣能使衍生類別有更合理的結構。事實上,有些類是專門作為基類而設計的,在設計時充分考慮到衍生類別的要求。
2) 調整從基類接收的成員
接收基類成員是程式人員不能選擇的,但是程式人員可以對這些成員作某些調整。例如可以改變基類成員在衍生類別中的訪問屬性,這是通過指定繼承方式來實現的。如可以通過繼承把基類的公用成員指定為在衍生類別中的訪問屬性為私人(衍生類別外不能訪問)。此外,可以在衍生類別中聲明一個與基類成員同名的成員,則衍生類別中的新成員會覆蓋基類的同名成員。但應注意,如果是成員函數,不僅應使函數名相同,而且函數的參數表(參數的個數和類型)也應相同,如果不相同,就成為函數的重載而不是覆蓋了。用這樣的方法可以用新成員取代基類的成員。
3) 在聲明衍生類別時增加的成員
這部分內容是很重要的,它體現了衍生類別對基類功能的擴充。要根據需要仔細考慮應當增加哪些成員,精心設計。例如在前面例子中(請查看:C++衍生類別的聲明方式),基類的display函數的作用是輸出學號、姓名和性別,在衍生類別中要求輸出學號、姓名、性別、年齡和地址,不必單獨另寫一個輸出這5個資料的函數,而要利用基類的display 函數輸出學號、姓名和性別,另外再定義一個display_1 函數輸出年齡和地址,先後執行這兩個函數。也可以在 display_1 函數中調用基類的display函數,再輸出另外兩個資料,在主函數中只需調用一個display_1函數即可,這樣可能更清晰一些,易讀性更好。
此外,在聲明衍生類別時,一般還應當自己定義衍生類別的建構函式和解構函式,因為建構函式和解構函式是不能從基類繼承的。
通過以上的介紹可以看出:衍生類別是基類定義的延續。可以先聲明一個基類,在此基類中只提供某些最基本的功能,而另外有些功能並未實現,然後在聲明衍生類別時加入某些具體的功能,形成適用於某一特定應用的衍生類別。通過對基類聲明的延續,將一個抽象的基類轉化成具體的衍生類別。因此,衍生類別是抽象基類的具體實現。
C++衍生類別的聲明方式(定義方式)
先通過一個例子來說明怎樣通過繼承來建立衍生類別,先從最簡單的單繼承開始。
class Student1: public Student //聲明基類是Student{public: void display_1( ) //新增加的成員函數 { cout<<"age: "<<age<<endl; cout<<"address: "<<addr<<endl; }private: int age; //新增加的資料成員 string addr; //新增加的資料成員};
假設已經聲明了一個基類Student(基類Student的定義見上節:C++繼承與派生的概念),在此基礎上通過單繼承建立一個衍生類別Student1:
仔細觀察第一行:
class Student1: public Student
在class後面的Student1是建立的類名,冒號後面的Student表示是已聲明的基類。在Student之前有一關鍵宇public,用來表示基類Student中的成員在衍生類別Studeml中的繼承方式。基類名前面有public的稱為“公用繼承(public inheritance)”。
請大家仔細閱讀以上聲明的衍生類別Student1和基類Student,並將它們放在一起進行分析。
聲明衍生類別的一般形式為:
class 衍生類別名:[繼承方式] 基類名 { 衍生類別新增加的成員 };
繼承方式包括public (公用的)、private (私人的)和protected(受保護的),此項是可選的,如果不寫此項,則預設為private(私人的)。