程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 由struct的靜態構造函數說起

由struct的靜態構造函數說起

編輯:C++入門知識

最近才知道struct和class的靜態構造函數的觸發規則是不同的,不像class在第一次使用類的時候觸 發靜態構造函數。如果只訪問struct實例的字段是不會觸發靜態構造函數調用的。通過測試發現當訪問靜 態字段,struct本身的函數(靜態和實例)和帶參數的構造函數就會引起靜態構造函數的執行。而調用默 認構造和未覆寫的基類虛函數是不會的。為什麼呢?

讓我們先來看看class和struct在調用構造函數時的區別。class使用newobj指令而struct使用initobj 指令來構造對象。newobj在堆上申請一塊內存並調用相應的構造函數進行初始化,然後將對象地址返回給 計算棧。initbobj則是從本地變量表中載入已經分配出來的struct實例然後初始化struct的各字段。這個 初始化過程是CLR內部執行的,而不像class編譯器會給class添加一個默認構造函數(這就是為什麼 struct不能給字段添加默認值的原因。但在類中如果給字段添加了默認值編譯器就會自動在構造函數中添 加字段賦值操作)。如果給struct中定義了一個有參數的構造函數,那麼系統就不會使用initobj指令, 而是直接用call指令調用帶參數的構造函數。

我們最常見最常用的調用函數的指令是call和callvirt。對於靜態函數使用call指令,對於class使用 callvirt指令(不論class中的函數是不是虛的)。只有子類調用父類的函數的時候(避免遞歸調用)以 及構造函數中(由編譯器添加保證父類字段被初始化)使用call指令。而對於struct我們發現只要調用的 函數是struct本身定義的都是使用call指令。call和callvirt指令的差別在於,call會把調用的函數當作 靜態函數看待,而不會關心調用當前函數時實例指針(this)是否為空。這就是struct調用函數時為什麼 都是call因為struct實例是不可能被置為null的。實際上class在調用非虛函數時實際上也是使用call的 只是多做了一步驗證——this是否為空,讓我們來驗證一下。

class Class_Test{  public void Test1() {}  public virtual void Test2()

{}  public static void Test3() {}  public override string ToString()  

{    return base.ToString();  }}Class_Test c = new Class_Test

();c.Test1();c.Test2();Class_Test.Test3();string str = c.ToString();

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved