第四章 型別基礎

2022-01-15 02:50:20 字數 3645 閱讀 2381

這章不好理解,我是連抄帶找的。。。。。。。。。。。

一、system.object

所有型別的基類,也就是所有型別從它派生。

公開了幾個方法:

equals : 判定兩個物件是否具有相同的值(相等性和同一性後續討論 )

gethashcode

tostring() 預設返回型別的完整名稱,但是經常會重寫返回表示物件狀態的

string

。例如:

int32

的tostring()

顯示欄位的值

gettype:返回從

type

派生的乙個型別的例項,呼叫的物件是什麼型別。

memberwsiseclone: 深度拷貝

finalize : 在垃圾**器判定物件是垃圾後,在物件的記憶體被實際**之前,呼叫這個虛方法。需要在**記憶體之氣那執行新區管理工作的型別應該重寫該方法。順便說下:

finalize

是會先執行父類

finalize

如果父類

finalize

執行後,子類再執行

finalize

時候會引發異常。具體後面介紹。

二、new 關鍵字

dog  dog= new dog(「旺財」);

作用1、計算型別及其所有基型別(一直到 system.object )中定義的所有例項欄位所需要的位元組數。物件含有額外位元組開銷,(

1.型別物件指標  

2.同步索引快 )

clr利用這些成員管理物件。額外成員的位元組數要計入物件的大小

2、從託管堆中分配型別要求的位元組數,從而分配物件的記憶體,分配的所有位元組都設為零(0)

3、初始化物件的型別指標和同步索引成員

4、呼叫型別的例項構造器,傳遞在new呼叫中指定的實參(

eg:旺財)編譯器都在構造器中自動生成**來呼叫基類構造器 ,每個型別的構造器否負責初始化該型別定義的例項字段,最終呼叫

system.object

的構造器。因為沒有定義任何例項字段所以該構造器什麼都不做,直接返回。

三、型別轉換 is  和

as1、型別轉化規則: 子類可以直轉為基類  

public class dog:anmial{}

狗是動物, anmial animal=new dog();

基類不能直接轉化為子類

dog dog=new animal(); (x) 可以這麼理解編譯器要做型別推斷,但是呢動物不一定是狗還可能是人或者別的動物貓。另外,語法安全上也是要求不能直接從基類轉為子類。

2、is 和

as 型別需要轉化通常我們會這樣: 因此各自利弊自己選擇

void getname(anmial animal)

if(animal is dog) //此處會做兩次的型別檢查

,失敗返回

false

void getname(anmial animal)

dog dog=animal as dog; //此處會做一次次的型別檢查 ,失敗返回

null

if(dog !=nul)

四、執行時的相互關係

簡單方法的呼叫需要預先知道的術語:

a:程序、執行緒(後面章節詳細介紹)

b:執行緒棧:

clr建立執行緒時候會分配

1m序幕**(開場

):我也很無奈為啥翻譯成這個名字,

prologue

開始執行方法前初始化變數,在棧上分配記憶體

尾聲**(後記

):我也很無奈為啥翻譯成這個名字,

epilogue

執行完後清理記憶體並且返回到呼叫者。

程式執行開始後,載入乙個clr的乙個

windows

程序,程序有多個執行緒。執行緒建立時候會分配到

1m的棧,棧空間用於向方法傳遞實參,實參,實參,方法內部定義的區域性變數也在棧上,棧上已經有了一些資料了(頂部陰影)。現在執行到了

m3的方法。

執行m3時候,

clr會初始化

m3的方法,包括開場**和結束**,開場**用來初始化區域性變數並且分配記憶體,引用型別指向

null,

值型別設定為

1.執行時

-值型別的分配和方法呼叫

圖中3的返回位址是在

m3中呼叫執行

m2的時候,壓棧進去的,目的是告訴排程指標執行完

m2的時候記得返回這裡,執行

m2的時候類似的分配空間,執行完

m2之後 4,

5將會被結束**(

clr叫做尾聲**,這什麼鬼翻譯!)清除掉,專業術語叫做 棧針

unwind

行為,同時棧針指向

3繼續執行,當執行完

m3時候同樣重複清除,棧針指向呼叫

m3的返回位址,(該位址在 執行緒棧

0位置下方,

1位置上方一點)這樣就結束了方法呼叫。

同理要分配乙個執行緒棧,呼叫方法前,有個序幕**、和尾聲**。行為和上面講到的一致。

執行時-引用型別和方法的呼叫

此處我們更關注堆上的變化

當執行到 new的關鍵字作用:結算物件占用記憶體大小(物件的型別指標大小,同步索引快、區域性變數、基類型別消耗的字段等一直計算到

object

)之後上形成如圖:

17行**執行完畢後形成如下圖示:結合**部分注釋和下圖理解執行時和方法的呼叫。

type型別物件:所有型別物件的基類,它的型別物件指標指向自己。

現在解釋下

你方法中的的gettype() 時候自己沒有定義為什麼能呼叫到,開始我們講了這個呢是基類的

object

的非虛方法

gettype()

,而且圖中的

dog型別物件

animal

型別物件,都是

type

的乙個例項,因此就知道了你呼叫的物件的實際型別。(具體怎麼知道?看下面解釋)

型別本質上也是物件,clr建立型別物件時,必須初始化以上型別在分配時包含的成員,初始化成什麼呢?clr開始在乙個程序中執行時,會立即為強命名程式集

mscorlib.dll

中定義的

system.type

型別建立乙個特殊的型別物件。

而我們自定義的使用者型別都是該型別的「例項

」。也就是物件指標指向 type型別物件。

當我們呼叫gettype()是時候返回的是:存貯在特定型別物件上的成員的位址指標。

這個怎麼理解呢就是你呼叫dog.gettype()返回的是存貯在

type

型別上的物件型別指標位址,

即dog

型別物件指標,返回了

dog型別物件指標自然就知道了

dog是什麼型別了。

物件型別指標和同步索引快、字段空間、方法位址空間=**。以後以**相稱

第四章 型別基礎

4.1 所有型別都從system.object派生 執行時 要求每個型別最終都從system.object型別派生。system.object 公共例項方法 equals 如果兩個物件具有相同的值,就返回true。gethashcode 返回物件的值得雜湊碼。如果某個型別的物件要在雜湊表集合中作為建...

《CLR via C 》第四章《型別基礎》

在coding中,任何型別都是繼承於system.object的,形如public class physicalgc basecommand其實完整的寫法應該是public class physicalgc basecommand system.object既然繼承了system.object,那就...

第四章 復合型別

第一題 按示例請求顯示資訊。第二題 修改程式4.4,使用c string類 include include using namespace std int main 第三題 使用char陣列,和cstring中的函式,按示例格式顯示輸出 include include using namespace...