C C 類的學習(四) 繼承與虛函式

2021-08-19 03:55:02 字數 4304 閱讀 1503

物件導向程式設計的核心思想是資料抽象、繼承和動態繫結(也稱之為動態聯編)。通過資料抽象將類的介面與實現分離;使用繼承可以定義相似的型別並對相似的關係建模;使用動態繫結可以在一定程度上忽視型別的區別,使用統一的方式使用他們的物件。

類是c++實現物件導向程式設計的手段,乙個類把一類事物的相同屬性通過資料成員和成員函式的形式囊括起來,方便直接使用。前面的幾篇博文中講述了關於類的一些基本性質,今天介紹一下類的繼承。

某個學校為了統計學生資訊(包括姓名、年紀)設計了乙個student類,這個類的成員變數包括姓名和年紀。而生物醫學工程系也想統計自己學院學生的資訊(包括姓名、年紀、年級、加權成績),這是就可以利用類的繼承,通過bme_student類繼承student類,只需要在bme_student類中新增年級、加權成績這兩個屬性即可,這無疑減小了工作量。

上面只是乙個舉例,是想說明當遇到需要擴充套件某乙個類的功能時,c++提供了一種比修改和擴充套件類更好的方法叫做繼承。下面我們還是以這兩個類為例進行介紹。

被繼承的類稱為基類,也可以叫父類。對應地,直接或者間接從基類繼承得到的類稱為派生類,也可以稱之為子類。一般基模擬較抽象,用於定義其所有子類的公共屬性,派生類繼承了這些公有屬性並且新增自己的屬性從而使特徵和功能更加具體化。

在c++中支援乙個派生類繼承多個基類,其形式如下;

class 派生類名: 派生方式基類名1, 派生方式 基類名2,...

;

這裡的派生方式包括公有的派生(public)、私有的派生(private)、保護的派生(protect)。無論哪種派生方式,基類中的private成員在派生類中都是不可見的,基類中的private成員不允許外部函式或派生類中的任何成員訪問,派生類想要訪問基類的私有成員只能通過基類的公有和保護的方法訪問。

公用的派生方式表示派生類從基類公有地繼承,基類中的成員在派生類中的訪問屬性除了私有的不可見以外,其他的保持不變;而私有的繼承方式,讓基類中公有成員和保護成員在派生類中都變成私有的;保護的繼承方式讓基類中公有成員和保護成員在派生類中都變成受保護的。具體的訪問形式如下面的**所示。

派生方式

private

public

protect

基類成員

private

public

protect

private

public

protect

private

public

protect

派生類

不可見可見(private)

可見(private)

不可見可見

(public)

可見(protect)

不可見可見

(protect)

可見(protect)

外部函式

不可見不可見不可見

不可見可見

不可見不可見

不可見不可見

student類記錄了學生的姓名及年齡。另外還定義了乙個公有的成員函式show();

class student

;//----------實現基類的函式;

student::student()

student::student(string fn, string ln, int ages) :firstname(fn), lastname(ln), age(ages)

student::~student()

student::student(const student &stu)

void student::show()

虛函式並不是說這個函式可以不被實現,定義虛函式是為了允許用基類的指標來呼叫子類的這個函式,實現動態多型,要與純虛函式分開。

某成員函式在基類中被定義為虛函式,在派生類中該函式無需新增virtual也預設為虛函式;若沒有在派生類重新定義,則將使用基類的版本;

建構函式不能使虛函式,析構函式應當是虛函式。因為,如果基類指標指向的是子類物件,將呼叫子類的析構函式,然後自動呼叫基類的析構函式。如果析構函式不是虛函式,則不會呼叫派生類的虛函式。而且,當基類的析構函式宣告為虛函式後,即便子類的析構函式與其名字不同,也一樣自動成為虛函式。友元不是成員函式,只有成員函式才可以是虛的,因此友元不能是虛函式。但可以通過讓友元函式呼叫虛成員函式來解決友元的虛問題。

只有通過指標和引用才能展現虛函式的特性。

重新定義虛函式不是過載,而是覆蓋(或是隱藏),即使派生類中重新定義了虛函式,無論函式列別是否相同,都將隱藏同名的基類方法。所以當基類中虛函式被過載時,在派生類中應該定義所有的版本。

靜態成員函式不能是虛函式;  內聯函式不能為虛函式; 

成員函式被過載是發生在同乙個類中,特徵是:

相同的範圍(在同乙個類中);

函式名字相同;

引數不同;

virtual 關鍵字可有可無。

覆蓋是指派生類函式覆蓋基類函式,特徵是:

不同的範圍(分別位於派生類與基類);

函式名字相同;

引數相同;

基類函式必須有virtual 關鍵字。

「隱藏」是指派生類的函式遮蔽了與其同名的基類函式,規則如下:

如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。

如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual 關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)

將源**中的函式呼叫解釋為特定函式**塊的行為被稱為函式名聯編(binding),在c++中,編譯器必須檢視函式引數以及函式名才能確定使用哪個函式,編譯器在編譯過程完成聯編,在編譯過程中完成的聯編稱為靜態聯編(static binding)。然而虛函式無法在編譯時確定使用哪個函式,所以編譯器只能在程式執行時選擇正確的虛函式**,這種聯編稱為動態聯編(dynamic binding)。

注意:動態聯編發生在基類指標呼叫虛函式時,因為此時無法判斷呼叫的是哪個函式,但是當物件呼叫虛函式是,編譯器可以直接判斷出呼叫哪個函式,因此是靜態聯編。

/*

//---類的繼承與虛函式

//---不用先生2018.04.21

*/#ifndef head01_h

#define head01_h

#include #include using namespace std;

//-----------基類為學生類--------------//

class student

;//----------實現基類的函式;

從結果中不難看出,在建立派生類物件時,首先呼叫基類建構函式,然後再呼叫派生類建構函式,而在進行析構時,先呼叫派生類物件,再呼叫基類建構函式。

因為是公用的繼承,所以student類中的show()函式可以直接被bme_student類中的show( )函式呼叫,但是一定要注以student::,否則將陷入無限迴圈。

由於show( )被定義為虛函式,所以指標p_stu呼叫的是派生類的show()函式。

已完。。

參考書籍《c++  primer 第五版》、《c++ primer plus 第六版》

【c++】c++類的學習(一)——初識類

【c++】c++類的學習(二)——建構函式、析構函式、拷貝建構函式以及this指標

【c++】c++類的學習(三)——運算子過載與友元函式

【c++】c++類的學習(五)——純虛函式與模板類

C C 類的繼承 多型與虛函式 過載

物件導向的程式設計主要目的是提供可重複利用的 類的繼承也是 重用的一種方式。從已有的類 基類 派生出新的類,派生類 繼承了原有類的特性,同時在其基礎上進行擴充套件增加功能。1.繼承 派生類可以訪問基類的公有成員 派生類不能直接訪問基類的私有成員,必須通過基類的公有函式間接訪問私有成員 派生類的建構函...

C C 車類的繼承與派生(虛基類)

問題描述 宣告乙個車 vehicle 基類,具有maxspeed,weight等成員變數,run,stop等成員函式,其中run函式輸出 run stop函式輸出 stop 並由此派生出自行車 bicycle 類,汽車 motorcar 類。自行車 bicycle 類有高度 height 等屬性,汽...

多重繼承 虛繼承與虛基類

一 多重繼承 單重繼承 乙個派生類最多只能有乙個基類 多重繼承 乙個派生類可以有多個基類 class 類名 繼承方式 基類1,繼承方式 基類2,派生類同時繼承多個基類的成員,更好的軟體重用 可能會有大量的二義性,多個基類中可能包含同名變數或函式 多重繼承中解決訪問歧義的方法 基類名 資料成員名 或成...