C 物件導向 繼承

2022-07-04 04:00:08 字數 4293 閱讀 6150

一、通過繼承(inheritance)可以在建立新類時復用、擴充套件和重寫已在其它類中宣告的可訪問的例項成員(除建構函式和析構函式外),類完全支援繼承,可以繼承自類也可以實現介面,結構不支援繼承,只可以實現介面;繼承是通過派生(derivation)實現的,被繼承的類稱為基類(base class),繼承的類稱為派生類(derived class);通過在派生類的名稱後面新增冒號和基類名稱來指定繼承的基類:

class

mybaseclass

}class myclass : mybaseclass //

mybaseclass是myclass的基類,myclass是mybaseclass的派生類

使用時:

new myclass().mybasefunc(); //

myclass繼承了mybaseclass的例項成員

1.從概念上來說,派生類是基類的專門化,派生類會隱式獲得基類中所有可訪問的例項成員(除建構函式和析構函式外),派生類可以復用基類中的**,而無需重新實現;派生類可以新增更多的成員,以擴充套件基類的功能;當基類中包含虛方法時,派生類可以重寫該方法以實現不同的功能;

2.派生類只能有乙個直接基類,但是,繼承是可傳遞的,例如classc派生自classb,classb派生自classa,那麼classc會繼承在classb和classa中宣告的可訪問的例項成員;

3.派生類的可訪問性不允許高於基類的可訪問性,即公共類可以派生出內部類和公共類,而內部類只能派生出內部類;不能繼承自密封類;

4.所有沒有顯式繼承基類的類都直接繼承自基類system.object;

5.類可以宣告為密封的來防止被其它類繼承;

6.在派生類中可以直接訪問基類中的非私有靜態成員,也可以直接或通過關鍵字base在任意位置訪問直接基類(即派生類所直接繼承的基類)中的非私有例項成員:

public

void

myfunc()

7.派生類的例項可以通過隱式轉換為基類型別的變數:

mybaseclass myobj = new myclass();

※此時myobj依然是myclass型別的例項,使用myobj.gettype()方法獲得的型別物件也是myclass型別的:

myobj.gettype().name //

myclass

※對於該物件,還可以通過顯式轉換或as運算子轉換為派生類的物件然後賦值給派生類型別的變數,其原例項的任何資料都不會修改或丟失,詳見:

myclass myclass = (myclass)myobj; //

※這個操作需要變數myobj也是由myclass或其派生型別的物件轉換來的,不能直接將基類物件轉換為派生類變數,會丟擲異常invalidcastexception,如果myobj是由其它派生類的物件轉換來的,而且該派生類和myclass無法直接進行轉換,則也會丟擲這個異常;正確的做法是先使用is判斷是否可以轉換,如果可以再使用強制轉換或as進行轉換,也可以不進行判斷直接使用as進行轉換,轉換失敗時會返回null;

8.派生類中如果需要有與基類相同名稱的成員,需要使用關鍵字new來隱藏基類中的成員,如果不顯式使用new,編譯器會丟擲警告並預設使用new來處理:

public

newvoid mybasefunc() {}

※此時將派生類的物件隱式轉換為基類的變數再訪問該名稱的方法時呼叫的依然是基類中的方法;

※此時在派生類中依然可以使用關鍵字base訪問基類中宣告的該同名成員;

二、如果基類中包含虛成員(virtual member,只包括方法、屬性、事件和索引器),那麼在派生類中可以通過關鍵字override重新實現此成員,重新實現的成員被稱為重寫成員(overridden member);重寫成員被看作是在派生類中宣告的對基類虛成員的新實現,將代替基類中的虛成員,即通過將派生類物件隱式轉換為基類變數時不能再訪問基類的此虛成員,而是訪問派生類中重寫後的成員:

public

class

baseclass

}public

class

myclass : baseclass

}

使用時:

baseclass myobj = new

myclass();

myobj.myfunc();

//overridden myfunc

※通過反射可以得知,使用override重寫方法時,派生類的型別物件中只包含乙個該名稱的方法,即覆蓋了基類中的虛方法,因此對於派生類物件,無論將其作為派生類變數訪問還是作為基類變數訪問,都只能訪問到派生類中的重寫方法;

※重寫成員依然具有虛效果,在後續派生類中同樣可以重寫該成員;

※如果派生類中除了重寫方法,還宣告了該方法的過載方法,則在呼叫時會優先匹配派生類中直接宣告的過載方法,再匹配派生類中對基類重新實現的重寫方法,例如:

public

class

myclass : baseclass

}public

class

myclass : baseclass

public

void myfunc(double

num)

}

使用時:

baseclass myobj = new

myclass();

myobj.myfunc(

1); //

overloaded myfunc

※由於變數1可以隱式轉換為double型別,因此編譯器將呼叫myfunc(double num),而不是myfunc(int num),有兩種方法可以避免此情況:1.避免新宣告的方法與虛方法命名相同;2.可以將派生類的例項顯式轉換為基類來使編譯器搜尋基類的方法列表,從而呼叫基類中的該方法,由於該方法已被派生類重寫,所以最終呼叫的是派生類中的重寫方法

※如果基類中有虛方法a和b,其中方法b中呼叫了方法a,派生類中只重寫了方法a,那麼在呼叫執行時型別為派生類的變數的方法b時,其中在呼叫方法a時呼叫的是派生類中重寫過的方法a;

1.如果不想讓基類中的虛成員被代替,則應該在派生類中通過關鍵字new隱藏此虛成員並提供新的實現,此成員被稱為替換成員(replaced member);替換成員只是隱藏而不會代替基類中的虛成員,此時通過將派生類物件隱式轉換為基類變數時訪問到的依然是基類中的虛成員;

※通過反射可以得知,使用new隱藏基類虛方法並提供新的實現時,派生類的型別物件中包含兩個該名稱的方法,其中乙個是派生類中新宣告的方法,另乙個是基類中被隱藏的虛方法,此時訪問派生類物件,編譯器會根據變數的執行時型別找到對應的方法,即執行時型別為派生類時訪問的是派生類中新實現的方法,執行時型別為基類時訪問的是基類中的虛方法;

※替換成員隱藏了基類中的虛成員,在後續派生類中也不可以再重寫該成員;

2.即使在派生類中重寫或隱藏了基類的虛成員,也可以在派生類的任意位置通過關鍵字base訪問直接基類中該虛成員的實現;推薦在派生類中的重寫成員時通過關鍵字base呼叫直接基類中該成員的實現,使派生類能夠集中精力實現屬於派生類的特殊行為:

public

override

void

myfunc()

※通過這種方式,還可以獲取基類中宣告虛自動屬性時初始化的值;

3.在繼承關係中,不管派生類中是否重寫了虛成員,只要沒有替換虛成員,虛成員的虛效果都會一直傳遞下去,除非在派生類中使用組合關鍵字sealed override重寫虛成員並將其指定為密封的,此時將取消該成員的虛效果,該派生類的後續派生類中不可以再重寫該成員,從而阻止該成員的進一步派生;與使用替換成員阻止派生不同的是,使用這種方式宣告的成員依然是重寫方法,會代替基類中的虛成員,轉換為基類變數使用時呼叫的依然是當前類中的重寫成員:

public

sealed

override

void

myfunc()

三、如果派生類繼承自乙個抽象類,就必須在派生類中通過關鍵字override實現抽象基類中所有的抽象成員,除非派生類也是抽象的:

public

abstract

class

myabstractclass

public

class

myclass : myabstractclass

}

※如果派生類也是抽象類,則會預設繼承基類中的抽象成員而無需實現;

※派生類的派生類中可以使用override重寫該成員,也可以使用new替換該成員;

1.虛成員、抽象成員和重寫成員、替換成員是多型的基礎;

出處:

c 物件導向 繼承

三 繼承 1.繼承的型別 實現繼承和介面繼承 2 介面繼承 表示乙個型別只繼承函式的簽名,沒有繼承任何實現 在需要指定該型別具有某些可用的特性時,最好使用這種型別的繼承。2.多重繼承 c 不支援多重繼承,為簡化 的繁瑣,可以允許型別派生自多個介面 多重介面繼承。這說明c 可以派生自另乙個類和任意多個...

物件導向c 之繼承

物件導向三大機制包括 1.封裝,隱藏內部實現。2.繼承,復用現有 物件導向最顯著的特徵 3.多型,改寫物件行為。繼承,是一種復用的手段。是從先輩處得到屬性和行為特徵。類的繼承就是新的類從已 有 的類那裡得到已有的特徵。類成員的訪問限定有三種 public,protected,private,在類外可...

c 物件導向之繼承

1 什麼是繼承?繼承簡單來理解就是子承父業,也即是孩子可以直接使用父親的東西,這樣自己就可以少奮鬥一些,父親有的東西可以直接拿過來用。2 程式設計中為什麼要用繼承?在程式設計中,對程式猿來說最想做的就是用盡可能少且高效的 實現想要的功能。就像好多人都不願白手起家一樣,直接繼承父母的財產,使用繼承可以...