C 學習筆記

2021-09-21 18:51:31 字數 4397 閱讀 9293

公有繼承

class student: public person		// 宣告為類person的公有派生類

;

當乙個類派生自共有基類時, 基類的公有成員是派生類的公有成員, 基類的保護成員是派生類的保護成員,基類的私有成員不能被派生類所直接訪問。

私有繼承

class student: private person		// 宣告為類person的私有派生類

;

基類的保護成員和公有成員都將成為派生類的私有成員

保護繼承

class student: protected person		// 宣告為類person的私有派生類

;

基類的共有和保護成員都將成為派生類的保護成員

如果不給出繼承方式,系統自動判定為私有繼承(那就完了)。

class person

// 設定姓名

};class student: public person // 宣告為類person的派生類

// 建構函式

};

派生類具有自己這些函式,派生類不能夠繼承基類的建構函式(包括拷貝建構函式), 析構函式和過載運算子派生類的引數初始化表要包含**「基類建構函式名(參數列)」**,表示呼叫基類的建構函式初始化基類的資料成員(初始化派生類要先初始化基類

如果基類建構函式是無參建構函式,有預設值的建構函式,那麼在初始化派生類的時候可以不不使用基類建構函式

系統在建立派生類物件時,首先去呼叫基類的建構函式初始化基類資料成員,然後是派生類物件資料的初始化。所以建構函式的執行順序可以形象地描述為「先執行基類建構函式,後執行派生類建構函式

派生類中一旦重置基類成員函式,基類中所有同名成員均被覆蓋。

這時候如果想呼叫基類的同名函式,必須在該函式前面加上基類名字和作用域運算子::

析構函式的呼叫順序和建構函式相反,先呼叫派生類的析構函式再呼叫基類的析構函式

1.引數傳遞時如果形參是引用或者類物件指標,那麼可以傳遞同類物件和派生類物件,不能傳遞祖先類物件

2.引數傳遞時如果形參是類物件(傳值), 那麼只能傳遞同類物件,不能傳遞祖先類物件,也不能傳遞派生類物件(存在切片問題)關於切片問題

3.在物件賦值時的情況和物件引數傳遞類似

當基類和派生類有同名函式時利用賦值相容原則正確呼叫函式的兩個條件:同名函式是虛函式, 且傳值或引數傳遞是遵守以上規則。缺一不可

設由類a派生出類b,再由類b派生出類c,這種繼承關係稱為多級繼承

如果b私有繼承a後又派生出c,那麼a中的公有和保護成員在b中都是私有成員,因此a的成員在c中都是不可訪問的,也就是對a功能的繼承元函式所訪問,因此a的功能可以被c間在b中就終止了

而如果b保護繼承a後又派生出c,那麼a中的公有和保護成員在b中都是保護成員,a的公有成員和保護成員可以被c的成員函式或友接繼承

如果乙個派生類有兩個或更多個基類,那麼這種行為稱為多繼承,多繼承的派生類的宣告一般格式如下:

class 派生類名: 繼承方式1 基類名1, 繼承方式2 基類名2……

;例如已宣告了類a和類b,可按如下方式宣告多繼承的派生類c:

class c: public a, private b

建構函式

建構函式初始化時和單繼承一樣, 不過是多寫基類建構函式名1(基類建構函式參數列1), 基類建構函式名2(基類建構函式參數列2)

建構函式和析構函式的執行順序

各基類可按任意順序排列,派生類建構函式的執行順序為:先呼叫基類的建構函式,再執行派生類建構函式的函式體。呼叫基類建構函式的順序是按照宣告派生類時基類出現的順序進行呼叫析構函式的執行順序與建構函式的執行順序正好相反

多繼承引起的多義性問題

菱形繼承會引起多義性

b類和c類都從a類派生出來,而d類通過多繼承由b與c共同派生。如果類a有成員函式show(),通過d的物件去訪問a類的成員函式show(),這時由於類b和類c都有繼承來自於類a的show()的副本,編譯器無法確定使用哪個副本,從而將發生編譯時錯誤資訊

解決方案:(1)新增作用域運算子

派生類物件名.基類名::資料成員名; // 訪問資料成員

派生類物件名.基類名::成員函式名(參數列); // 訪問成員函式

d obj;		// 定義物件

obj.b::show(); // 輸出資訊, 指定呼叫b中來自於a的show()的副本

system("pause"); // 輸出系統提示資訊

(2)虛基類虛基類是解決多義性問題的一種簡便而有效的方法。使用虛基類的方法,使得在繼承間接共同基類時只保留乙份成員副本,這樣將不會出現多義性問題虛基類由關鍵字virtual標識,一般語法格式如下:

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

虛基類不是在宣告基類時宣告,而是在宣告派生類時,在繼承方式前加關鍵字vitual加以宣告。

虛基類的建構函式先於非虛基類的建構函式執行虛函式要解決的問題是:當基類和派生類中有同名函式或者同名資料時, 而在主函式中又是利用賦值相容原則賦值基類物件(基類的指標指向派生類位址, 或者引用的傳遞), 這時被賦值的基類物件在呼叫同名函式時應該呼叫派生類的同名函式, 而不是基類的同名函式

在類繼承時,可以在派生類中重定義基類函式原型相同的函式,也就是在基類與派生類中可以同時定義函式名相同,引數個數和型別以及返回值型別都相同的函式

由於採用虛函式通過基類指標指向不同類物件實現多型性時,與指標指向的具體物件有關,因此c++規定虛函式不能宣告為靜態成員函式(因為靜態成員函式與具體物件無關)

指標指向乙個具體物件後,不能通過指標直接或間接呼叫建構函式,所以c++還規定建構函式也不能宣告為虛函式。

虛函式的宣告增加了關鍵字virtual,成員函式在類體外定義時不加關鍵字virtual

虛函式在基類宣告時一定要加關鍵字virtual,在派生類中宣告虛函式時可以省略關鍵字virtual

如果定義了乙個指向該基類的指標變數指向new運算子建立的派生類臨時物件。在程式中用delete運算子撤銷物件時,如果析構函式不是虛函式,由於是基類指標,只是指向派生類物件中的基類部分,從而系統會只執行基類的析構函式,不執行派生類的析構函式

如果將基類的析構函式宣告為虛函式,由基類所派生的派生類的析構函式也都自動成為虛函式(即使派生類的析構函式與基類的析構函式名不相同)

在c++程式設計時最好把基類的析構函式都宣告為虛函式。這樣當在程式中用delete運算子釋放乙個物件時,系統會呼叫相應類的析構函式

有時在基類中將某一成員函式宣告為虛函式,是考慮到派生類的需要,只在基類中預留了乙個函式名,讓具體功能在派生類中根據需要去實現。這時適合將基類的成員函式宣告為純虛函式,宣告純虛函式的一般形式是

virtual返回值型別 函式名(形參表) = 0;

純虛函式沒有函式體,所以純虛函式不能被呼叫,包含純虛函式的類是無法建立物件,而只作為一種用作繼承的基類,稱含有純虛函式的類為抽象類或抽象基類, 只要含有純虛函式就是抽象類

雖然抽象類不能定義具體物件,但可以定義抽象類的指標變數,用指標變數指向派生類物件,然後通過該指標呼叫虛函式,實現多型性的操作。也可以通過函式形參是抽象類基類的引用而實參是派生類物件實現多型性

C 學習筆記( )

一 語法 迴圈 foreach 型別識別符號 in 表示式 code 用法 例子int temp foreach int num in temp 每次從temp取乙個元素賦給num直至取完 console.writeline n num 每行顯示乙個元素 執行結果 c 中唯讀 只寫控制 class ...

C 學習筆記

1.函式特徵 有函式頭和函式體 接受乙個引數 返回乙個值 需要乙個原型。2.c 命名規則 在名稱中只能使用字母字元 數字和下劃線 名稱的第乙個字元不能是數字 區分大寫字母和小寫字母 不能將c 關鍵字用作名稱 以兩個下劃線或下劃線和大寫字母打頭的名稱被保留給實現 編譯器及其使用的資源 使用,以乙個下劃...

c 學習筆記

屬性 屬性開頭字母大寫 屬性可以判斷輸入的非法值 屬性本身不儲存值 依靠字段 索引器 using system using system.collections.generic using system.linq using system.text namespace b try catch exc...