C C 學習總結(四) 類與類之間的關係

2021-09-05 10:29:22 字數 4684 閱讀 3785

類與類之間的關係:組合(乙個類包含了其他類)、依賴(乙個類使用了其他類)和繼成(乙個類繼承了其他類)。

1、類的組合關係

某乙個或幾個類的物件作為其他某個類的成員,例:

class a

;class b

;class c

;

其中,x和y是普通的資料成員,a和b是物件成員。c類包含了a類和b類的物件,此時稱c與a和b之間的關係為組合關係。

2、物件成員的構造與析構

物件與它內部的物件成員有相同的生命週期。當建立乙個物件時,先呼叫物件成員的建構函式再呼叫物件自身的建構函式,析構時順序完全相反。

如果物件成員的建構函式需要傳遞引數,那麼這個引數傳遞的過程需要放在新類建構函式的初始化表中來解決,格式如下:

新類建構函式(新類建構函式實際參數列, 成員物件實際參數列):成員物件名(成員物件實際參數列)例:

class a

};class b

};

物件成員建構函式的呼叫順序與初始化表中的出現次序無關,它始終與物件成員在類中定義的次序一致。乙個物件中某乙個函式的實現需要另乙個物件,例:

class a

;class b

1、派生類的定義乙個新定義的類具有某個或某些舊類的功能與成員,但它又不完全與舊類相同,而是額外新增了一些功能和成員。舊類成為基類(父類),新類稱為派生類(子類)。在c++中乙個基類可以派生出多個派生類,乙個派生類也可以有多個基類,派生類也可以作為基類繼續派生出新的派生類。

派生類定義語法格式如下:

class 《派生類名》:[繼承方式] 《基類名1> [, [繼承方式] 《基類名2>, ... , [繼承方式] 《基類名n>] 

;

說明:

①派生類的定義方式與普通類定義類似,只是要在派生類名稱與類體之間必須給出繼承方式與基類名,對於單一繼承只有乙個基類名,對於多重繼承,有多個基類名,彼此之間以逗號分隔;

②繼承方式指明派生類是以什麼方式繼承基類,共有3種:public(公有)、private(私有)和protected(保護),如果預設則預設為私有繼承方式。

引入繼承機制的優勢是提高**的可重用性。

三種不同的繼承方式會導致基類成員的訪問屬性在派生類中會發生不同的變化。

(1)公有繼承

基類公有成員——>派生類公有成員

基類保護成員——>派生類保護成員

基類私有成員不可被繼承,在派生類中不可見。

(2)保護繼承

基類公有成員——>派生類保護成員

基類保護成員——>派生類保護成員

基類私有成員不可被繼承,在派生類中不可見。

(3)私有繼承

基類公有成員——>派生類私有成員

基類保護成員——>派生類私有成員

基類私有成員不可被繼承,在派生類中不可見。

總結:基類的私有成員不可以被繼承,因此在派生類中無法訪問。protected繼承和private繼承改變了基類成員的訪問屬性,限制了這些成員的進一步派生,因而在實際程式設計中極少使用。

2、派生類物件的構造與析構

(1)派生類物件的建構函式

對乙個派生類而言,新增加成員的初始化可以在派生類的建構函式中完成,其基類成員的初始化則必須在基類的建構函式中完成。c++中,這個工作需要借助派生類建構函式對基類建構函式的呼叫來實現,具體如下:

①如果基類建構函式沒有引數,那麼系統將預設呼叫基類的沒有引數的建構函式;

②如果基類建構函式需要傳遞引數,那麼要在派生類的建構函式初始化列表中對基類建構函式進行呼叫。

基類建構函式需傳遞引數時,派生類建構函式的語法格式如下:

《派生類名》(《總形式參數列》):《基類名1>(《參數列1>), 《基類名2>(《參數列2>)[, ...《基類名n>(《參數列n>), 《其它初始化項》]

說明:

①派生類只需負責直接基類建構函式的呼叫。若直接基類建構函式不需要提供引數,則無需在初始化列表中列出,但實質上也會自動呼叫基類建構函式的;

②基類建構函式的呼叫通過初始化列表來完成。當建立乙個物件時,實際呼叫次序為宣告派生類時各基類出現的次序,而不是各基類建構函式在初始化表中的順序。

③其它初始化項包括物件成員、常成員和引用成員等。另外,普通資料成員的初始化也可以放在這裡進行。

定義乙個派生類物件時,建構函式的呼叫順序為:基類建構函式、派生類物件成員建構函式(按定義順序)、派生類建構函式;析構函式的呼叫順序與此相反。

(2)派生類物件的析構函式

派生類析構函式只能完成對新增加資料成員的清理工作,而基類的則應由基類的析構函式完成。由於析構函式沒有引數,因此派生的析構函式預設直接呼叫了基類的析構函式。

3、同名衝突及其解決方案

(1)派生類與基類的同名衝突

派生類中的新成員名稱與基類中的某個成員同名,此時同名覆蓋將發生作用:無論是派生類成員函式還是派生類物件訪問同名成員,如果不加任何標識,訪問的都是派生類新定義的同名成員。而派生類成員函式或派生類物件若要訪問基類中的同名成員,則必須在同名成員前加上「基類名::」進行限定。

說明:①派生類指標或引用訪問的是派生類的同名成員;

②基類引用成為派生類物件別名時,訪問的是基類中的同名成員;

③基類指標指向派生類物件時,訪問的是基類中的同名成員;

④若通過基類指標或引用訪問派生類同名成員,設計下一章虛函式。

(2)多個直接基類引發的同名衝突

乙個派生類的多個直接基類中有同名成員,訪問時在成員前指明基類名即可訪問該基類成員。如:

class a

;class b

;class c:public a, public b

};

(3)共同祖先基類多重拷貝引發的同名衝突

設base類中有成員a,那麼在derived類中將會有兩個成員a。

以上問題的一種解決方法時通過base1::a或base2::a的方式來區分兩個a;

但是,在derived類中出現兩個a通常與實際不符,因此c++中提供了另外一種解決方案:虛基類

虛基類的定義通過關鍵字「virtual」來實現,語法格式如下:

class 派生類名:virtual 繼承方式 基類名;或

class 派生類名:繼承方式 virtual 基類名

;

virtual確保虛基類的建構函式至多被呼叫一次。程式執行時,系統會進行檢查:如果虛基類的建構函式還沒有被呼叫過,那就呼叫一次,如果已經被呼叫過了,那就忽略此次呼叫。

根據c++規定,只有最後一層派生類對虛基類建構函式的呼叫發揮作用,例:

class a

;class b1:virtual public a

{};class b2:virtual public a

{};class c:public b1, public b2

};

上例中,虛基類成員a的值最終為xa。

此時建立乙個物件時,其完整的構造函式呼叫順序是:所有虛基類建構函式——>所有直接基類建構函式——>所有物件成員的建構函式——>派生類自己的建構函式;析構函式與之相反。

4、賦值相容規則

所謂賦值相容規則是指需要使用基類的地方可以使用其公有派生類來代替,換言之,公有派生類可以當成基類來使用。公有派生類繼承了基類中除建構函式、析構函式以外的所有非私有成員,且訪問許可權也完全相同,因此當外界需要基類時,完全可以用它來代替。

賦值相容常見的4種情形:

①基類物件=公有派生類物件, 基類物件獲得基類成員部分,派生類中新增的成員不能被基類物件訪問;

②指向基類物件的指標=公有派生類物件的位址,利用賦值後的指標可以訪問派生類中的基類成員;

③指向基類物件的指標=指向公有派生類物件的指標,利用賦值後的指標可以訪問原指標所指向物件的基類成員;

④基類的引用=公有派生類物件,即派生類物件可以初始化基類的引用,賦值後的引用只可以訪問基類成員部分,不可以訪問派生類新增成員。

注意:使用賦值相容時,必須是公有派生類!!!

C C 語法 (四)類與結構體

演算法題中使用的類知識很少,所以沒啥好寫的.類與結構體的主要區別在於,如果不定義成員是公有或私有,類中預設設定為private,而結構體中預設設定為public.以下隨便寫點結構體語法,背過就完事了.struct person 無參建構函式 person int age,int height age...

類與類之間的四種關係

1 聚合aggregation 例如電腦由cpu 記憶體 硬碟組成 public class computer public ram ram public keyboard keyboard 又或者人群由人構成 public class clowd 2 關聯association 最常見的關係之一,...

學習筆記 類與類之間的關係

謝謝樓主分享 一 繼承關係 二 實現關係 三 依賴關係要借用一條船,此時人與船之間的關係就是依賴。表現在 層面,為類b作為引數被類a在某個method方法中使用。在uml類圖設計中,依賴關係用由類 四 關聯關係的,而且雙方的關係一般是平等的。關聯可以是單向 雙向的。表現在 層面,為被關聯類b以類的屬...