C 學習筆記基礎系列2

2021-09-12 09:10:29 字數 3826 閱讀 3224

類之間的關係

繼承和派生

1、子類擁有父類的所有成員變數和方法

2、子類可以擁有父類沒有的方法和屬性

3、子類就是一種特殊的父類

4、子類物件可以當作父類物件使用

多繼承的構造和析構,構造:從父類到子類,析構順序相反;

幾種繼承關係

public 繼承:父類成員在子類中保持原有訪問級別

private 繼承:父類成員在子類中變為 private 成員

protected 繼承:父類中 public 成員會變成 protected

父類中 protected 成員仍然為 protected(子類中可用)

父類中 private 成員仍然為 private (private只能在本類的內部訪問,而繼承的子類內部和外部都不能使用)

繼承中的同名成員變數處理方法

1、當子類成員變數與父類成員變數同名時

2、子類依然從父類繼承同名成員

3、在子類中通過作用域分辨符::進行同名成員區分( 在派生類中使用基類的同名成員 ,

顯式地使用類名限定符)

4、同名成員儲存在記憶體中的不同位置

派生類中的 static

基類定義的靜態成員,將被所有派生類共享

 根據靜態成員自身的訪問特性和派生類的繼承方式,在類層次體系中具有不同的訪

問性質 (遵守派生類的訪問控制)

 派生類中訪問靜態成員,用以下形式顯式說明:

類名 :: 成員

或通過物件訪問 物件名 . 成員

多繼承:乙個類有多個直接基類的繼承關係稱為多繼承

多繼承的派生類構造和訪問

 多個基類的派生類建構函式可以用初始式呼叫基類建構函式初始化資料成員

 執行順序與單繼承建構函式情況類似。多個直接基類建構函式執行順序取決於定義

派生類時指定的各個繼承基類的順序。

 乙個派生類物件擁有多個直接或間接基類的成員。不同名成員訪問不會出現二義性。

如果不同的基類有同名成員,派生類物件訪問時應該加以識別。

虛繼承

如果乙個派生類從多個基類派生,而這些基類又有乙個共同的基類,則在對該基類中宣告的名字進行訪問時,可能產生二義性

 如果乙個派生類從多個基類派生,而這些基類又有乙個共同

的基類,則在對該基類中宣告的名字進行訪問時,可能產生

二義性 如果在多條繼承路徑上有乙個公共的基類,那麼在繼承路徑的某處

匯合點,這個公共基類就會在派生類的物件中產生多個基類子物件

 要使這個公共基類在派生類中只產生乙個子物件,必須對這個基類

宣告為虛繼承,使這個基類成為虛基類。

 虛繼承宣告使用關鍵字 virtual

如上圖,class b其實是b1好b2的共同基類,b中的成員變數b則在c使用時無法得知是從b1繼承得到還是b2繼承得到(b呼叫兩次建構函式,加了virtual關鍵字則呼叫一次),虛繼承就可以解決這類問題。

多型一種呼叫語句 有多種表現形式

 c++中通過virtual關鍵字對多型進行支援

 使用virtual宣告的函式被重寫後即可展現多型特性

後續編寫的**,可以在之前編寫的框架下被呼叫起來。(介面)

多型成立的三個條件

//1 要有繼承

//2 要有虛函式重寫

//3 要有父類指標(父類引用)指向子類物件

(多型是設計模式的基礎,多型是框架的基礎)

多型的理論基礎

靜態聯編和動態聯編

1、聯編是指乙個程式模組、**之間互相關聯的過程。

2、靜態聯編(static binding),是程式的匹配、連線在編譯階段實現,也稱為早期匹配。過載函式使用靜態聯編。

3、動態聯編是指程式聯編推遲到執行時進行,所以又稱為晚期聯編(遲繫結)。

switch 語句和 if 語句是動態聯編的例子。

4、理論聯絡實際

1、c++與 c 相同,是靜態編譯型語言

2、在編譯時,編譯器自動根據指標的型別判斷指向的是乙個什麼樣的物件;所以編譯器認為父類指標指向的是父類物件。

3、由於程式沒有執行,所以不可能知道父類指標指向的具體是父類物件還是子類物件

從程式安全的角度,編譯器假設父類指標只指向父類物件,因此編譯的結果為呼叫父類的成員函式。這種特性就是靜態聯編

虛析構函式

1、記憶體洩漏例子:a b c三個類 b繼承a c繼承b ,

public :

a()virtual ~a()

protected:

private:

char *p;

}class b:public a

~b()

protected:

private:

char *p;

}class c : public b

~c()

protected:

private:

char *p;

}void howtodelete(a *base)

//想通過父類指標釋放所有子類成員 則需要在基類中的析構函式新增virtual關鍵字,否則只釋放a

//物件資源

void main()

重寫、過載和重定義函式過載必須在同乙個類中進行

子類無法過載父類的函式,父類同名函式將被名稱覆蓋

過載是在編譯期間根據引數型別和個數決定函式呼叫

函式重寫

必須發生於父類與子類之間

並且父類與子類中的函式必須有完全相同的原型

重寫分為兩類:

1、使用 virtual 宣告之後能夠產生多

2、(如果不使用 virtual,那叫重定義)

多型是在執行期間根據具體物件的型別決定函式呼叫

c++中多型的實現原理

存在虛函式時,每個物件中都有乙個指向虛函式表的指標(vptr 指標)

說明 1:

通過虛函式表指標 vptr 呼叫重寫函式是在程式執行時進行的,因此需要通過定址操作才能

確定真正應該呼叫的函式。而普通成員函式是在編譯時就確定了呼叫的函式。在效率上,虛

函式的效率要低很多。

說明 2:

出於效率考慮,沒有必要將所有成員函式都宣告為虛函式

說明 3 :c++編譯器,執行 howtoprint 函式,不需要區分是子類物件還是父類物件

C 基礎系列 反射筆記

前言 使用反射也有幾年了,但是一直覺得,反這個概念很抽象,今天有時間就來總結下這個知識點。1 為什麼需要反射 最初使用反射的時候,作為小菜總是不理解,既然可以通過new 乙個物件的方式得到物件,然後通過物件去呼叫屬性和方法,那麼為什麼還需要反射去呼叫呢?後來使用多了發現這就是乙個先繫結還是後繫結的問...

C 基礎系列 反射筆記

前言 使用反射也有幾年了,但是一直覺得,反這個概念很抽象,今天有時間就來總結下這個知識點。1 為什麼需要反射 最初使用反射的時候,作為小菜總是不理解,既然可以通過new 乙個物件的方式得到物件,然後通過物件去呼叫屬性和方法,那麼為什麼還需要反射去呼叫呢?後來使用多了發現這就是乙個先繫結還是後繫結的問...

C 基礎筆記2

16.2.4.2 逗號運算 關係運算 邏輯運算和條件運算1.逗號運算和逗號表示式 格式 表示式1,表示式2 求解順序及結果 先求解表示式1,再求解表示式2 最終結果為表示式2的值 2.關係運算與關係表示式 關係運算是比較簡單的一種邏輯運算,優先次序為 優先順序相同 高 優先順序相同 低 關係表示式是...