對C 繼承的理解

2021-10-14 02:25:08 字數 4632 閱讀 8884

繼承是可用傳遞的 , 子類是對父類的擴充套件 , 必須繼承父類的方法,同時在子類中新增新方法。

子類可用呼叫父類的公用方法和字段 , 而父類不能呼叫子類的成員。

子類不僅繼承了父類的共有成員 , 同時也繼承了父類的私有成員 , 只是在子類中不能被訪問。

繼承的三個關鍵字:

abstract 抽象。用來限定類時,類中的方法不能有方法實體;用來限定方法時,同樣也不能有方法實體,並且在子類中必須完成方法實體,除非子類繼續使用抽象方法。

virtual 用來指示類中的方法可以被子類的同名方法覆蓋或者共存,覆蓋時,子類中使用override關鍵字;共存時,使用new 關鍵字。

new 在子類方法中的用法是指子類中與父類存在的同名方法在方法列表敏感詞存,並不覆蓋父類的方法,這就達到了多型機制下並非一味覆蓋的效果。

swallow:bird bird:animal animal:object

在建立 swallow 物件的過程中,首先建立的是 swallow 類裡面的字段 , 字段建立完畢後 , 接著會建立其父類 bird, 並為其欄位分配儲存空間,然而 bird 繼承 animal ,在記憶體中也為 animal 類中的字段分配儲存空間 , 這樣依次尋找到最終的父類的 object 為止。在物件建立的過程中是按照順序完成了對整個父類及其本身欄位的記憶體建立,並且欄位的儲存順序是由上到下的排列, object 類的字段排在最前面。如果父類和子類出現了同名字段 , 則在子類物件建立時,編譯器會自動認為這是兩個不同的字段加以區分。

swallow 生成方法列表時,首先將父類 bird 的所有方法拷貝乙份,然後和 swallow 本身的方法進行對比,如果在子類中有 override 覆蓋父類的同名方法,則用子類的方法代替父類的方法,這樣就建立完成swallow的方法列表。這種建立過程也是逐層遞迴到object類,並且方法列表中也是按照順序排列的。

bird bird=new swallow(); 這種情況下bird.show();應該呼叫那個方法?有兩個原則,是.net專門解決這個問題。如下:

1) 關注物件建立原則:呼叫子類還是父類的方法,取決於建立的物件是子類物件還是父類物件,而不是它的引用型別。

2) 執行就近原則:對於同名的方法或者字段,編譯器是按照順序查詢來引用的,也就是首先訪問距離它最近的字段或者方法。

注意:ovveride重寫父類的方法是在位址列表中覆蓋了父類的方法,所以如果最終執行的是子類的物件,則執行了子類中的方法(因為覆蓋了父類方法的位址,第乙個原則)。

new是在子類中定義了與父類同名的方法,要隱藏父類的同名方法,在編譯器的時候其實是為父類和子類的兩個方法分配了位址,只不過父類方法排在前面,而子類方法排在後面,就近原則根據定義的型別來決定,這樣根據就近原則,如果定義的物件型別為父類,則就近找到父類的方法執行,而如果定義在子類的型別,則就近找到子類的方法執行。

簡單的測試邏輯**如下:

在這裡畫一下記憶體分布圖。

首先建立 swallow 裡面的字段 ( 對於屬性而言其本質就是一種方法 , 有 c# 編譯器自動實現 , 實現的結果就是 get_id(),set_id(int value) 這種最終的方法 過程請自行檢視 clr via c# 第三版或者第四版 這裡不再多說 ), 最後找到 object 但是裡面沒有字段 , 這裡就不進行建立。

類中的字段建立完畢後 , 進行方法的建立。首先生成 swallow 的方法列表時 , 先將其父類 bird 的方法 copy 乙份。 然後進行兩者比對

swallow 中的方法有 :

new public int get_id();

new public set_id(int value);

public override string get_color();

public override set_color(string value);

public override show();

private void showmyself();

bird 中的方法有 :

new public int get_id();

new public set_id(int value);

new public virtual void show();

private void showmyself();

下圖為記憶體中建立的圖

然後開始和父類 bird 中的方法進行比對。

new public int get_id(); new 表示隱藏 , 共存 但是記憶體中有父類和子類的 get_id

new public void set_id();new 表示隱藏 , 共存 但是記憶體中有父類和子類的 set_id

public override string get_color(); 父類不存在就建立子類的

public override set_color(string value); 父類不存在就建立子類的

public override show(); override 表示覆蓋 覆蓋父類中 show 方法,此時 bird 在記憶體中的 show 方法便指向了子類 swallow 中的 show 方法 ( 下圖中加粗線條顯示 )

showmyself 是私有的 , 在記憶體中同時存在。

這樣建立完畢後記憶體如下圖

然後開始 bird 方法的建立 , 因為記憶體中有了 bird 的方法 , 就直接建立 animal 方法

bird 中的方法有 :

new public int get_id();

new public set_id(int value);

new public virtual void show();

private void showmyself();

animal 的方法有 :

public int get_id();

public set_id(int value);

public virtual string get_color();

public virtual set_color(string value);

public void show();

private void showmyself();

按照上面的對比方法後兩者 (animal 和 bird) 記憶體中的狀態為

最後記憶體中完整的狀態如下圖:

然後自己根據記憶體中的狀態 進行分析呼叫程式即可。在c#中呼叫父類記得使用base,逐個除錯你會得到更多資訊。

注意 子類只拷貝父類中的方法,如果父類中沒有對應的方法,才會向上查詢,直至找到object類。

對C 繼承的理解

繼承是一種 復用的方式,使得我們不必寫重複的 例如,有三種怪物a b c,他們都有速度 血量 攻擊力 防禦值 攻擊方式。如果沒有繼承我們可能要寫三個指令碼monstera monsterb monsterc,而且在某個指令碼中我們還要重複的宣告定義變數speed等。如果這有三種怪物,那麼貼上複製起來...

對繼承的理解。

我的發帖。我的體會 0 在做前端的時候發現乙個繼承的適合場景,就是母模板和子頁面的關係。用繼承比組合恰當。1 繼承的根本目的是為了對要解決的問題進行更好的建模 2 繼承的目的不是復用,從某種意義上來說,恰恰是為了處理不能復用的場景。所以才有繼承。復用只是大多數優秀模型的乙個必然結果而已。3 從底層實...

對繼承對映的理解

繼承關係的對映策略有三種 每個繼承結構一張表 table per class hierarchy 不管多少個子類都用一張表。每個子類一張表 table per subclass 公共資訊放一張表,特有資訊放單獨的表。每個具體類一張表 table per concrete class 有多少個子類就有...