C 構造器的原理

2021-06-08 13:18:02 字數 2742 閱讀 1856

構造器負責類中成員變數(域)的初始化。c#的類有兩種構造器:例項構造器和靜態構造器。例項構造器負責初始化類中的例項變數,它只有在使用者用new關鍵字為物件分配記憶體時才被呼叫。而且作為引用型別的類,其實例化後的物件必然是分配在託管堆(managed heap)上。這裡的託管的意思是指該記憶體受.net的clr執行時管理。和c++不同的是,c#中的物件不可以分配在棧中,使用者只宣告物件是不會產生構造器呼叫的。

例項構造器分為預設構造器和非預設構造器。預設構造器是在乙個類沒有宣告任何構造器的情況下,編譯器強制為該類新增的乙個無引數的構造器,該構造器僅僅呼叫父類的無引數構造器。預設構造器實際上是c#編譯器為保證每乙個類都有至少乙個構造器而採取的附加規則。注意這裡的三個要點:

子類沒有宣告任何構造器;

編譯器為子類加的預設構造器一定為無引數的構造器;

父類一定要存在乙個無引數的構造器。

看下面例子的輸出:

using system;

public class myclass1

public myclass1(string param1) }

public class myclass2:myclass1}}

編譯程式並執行可以得到下面的輸出:

myclass1 parameterless contructor!

讀者可以去掉myclass1的無參構造器public myclass1()看看編譯結果。

構造器在繼承時需要特別的注意,為了保證父類成員變數的正確初始化,子類的任何構造器預設的都必須呼叫父類的某一構造器,具體呼叫哪個構造器要看構造器的初始化引數列表。如果沒有初始化引數列表,那麼子類的該構造器就呼叫父類的無引數構造器;如果有初始化引數列表,那麼子類的該構造器就呼叫父類對應的引數構造器。看下面例子的輸出:

using system;

public class myclass1

public myclass1(string param1)

}public class myclass2 : myclass1

}public class test

}編譯程式並執行可以得到下面的輸出:

myclass1 constructor parameters : hello

myclass2 constructor parameters : hello

c#支援變數的宣告初始化。類內的成員變數宣告初始化被編譯器轉換成賦值語句強加在類的每乙個構造器的內部。那麼初始化語句與呼叫父類構造器的語句的順序是什麼呢?看下面例子的輸出:

using system;

public class myclass1

public virtual void print()

}public class myclass2 : myclass1

public override void print()

}public class test

}編譯程式並執行可以得到下面的輸出:

x = 1, y = 0

x = 1, y = -1

容易看到初始化語句在父類構造器呼叫之前,最後執行的才是本構造器內的語句。也就是說變數初始化的優先權是最高的。

我們看到類的構造器的宣告中有public修飾符,那麼當然也可以有protected/private/ internal修飾符。根據修飾符規則,我們如果將乙個類的構造器修飾為private,那麼我們在繼承該類的時候,我們將不能對這個private的構造器進行呼叫,我們是否就不能對它進行繼承了嗎?正是這樣。實際上這樣的類在我們的類內的成員變數都是靜態(static)時,而又不想讓類的使用者對它進行例項化,這時必須遮蔽編譯器為我們暗中新增的構造器(編譯器新增的構造器都為public),就很有必要作乙個private的例項構造器了。protected/internal也有類似的用法。

類的構造器沒有返回值,這一點是不言自明的。

靜態構造器初始化類中的靜態變數。靜態構造器不象例項構造器那樣在繼承中被隱含呼叫,也不可以被使用者直接呼叫。掌握靜態構造器的要點是掌握它的執行時間。靜態構造器的執行並不確定(編譯器沒有明確定義)。但有四個準則需要掌握:

在乙個程式的執行過程中,靜態構造器最多隻執行一次。

靜態構造器在類的靜態成員初始化之後執行。或者講編譯器會將靜態成員初始化語句轉換成賦值語句放在靜態構造器執行的最開始。

靜態構造器在任何類的靜態成員被引用之前執行。

靜態構造器在任何類的例項變數被分配之前執行。

看下面例子的輸出:

using system;class myclass1

public static void method1()

}class myclass2

public static void method1()

}class test

}編譯程式並執行可以得到下面的輸出:

myclass1 static contructor

myclass1.method1

myclass2 static contructor

myclass2.method1

當然也可能輸出:

myclass1 static contructor

myclass2 static contructor

myclass1.method1

myclass2.method1

值得指出的是例項構造器內可以引用例項變數,也可引用靜態變數。而靜態構造器內能引用靜態變數。這在類與物件的語義下是很容易理解的。

實際上如果我們能夠深刻地把握類的構造器的唯一目的就是保證類內的成員變數能夠得到正確的初始化,我們對各種c#中形形色色的構造器便有會心的理解--它沒有理由不這樣!

C 構造器(建構函式)

定義和作用 構造器是在構建類的 引用時 自動執行的方法。所以,每個類都必須至少要有乙個構造器。在訪問乙個類的時候,編譯器最先執行構造器中的 它與類同名,帶引數的構造器能夠獲取引數,但是與方法不同的是 構造器雖然也是一種 例項型別 即必須通過例項來進行呼叫,也可以稱之為引用型別 但是卻不能返回任何值 ...

C 中的預設構造器和過載構造器

使用 new 關鍵字建立乙個物件時,runtime 必須使用那個類的定義來構造物件,runtime 必須從作業系統申請乙個記憶體區域,在其中填充由類定義的字段,然後呼叫乙個構造器執行必須的任何初始化工作。構造器 constructor 是一種特殊方法 method 它在建立類的乙個例項時自動執行。它...

C 類 構造器

class 類名 class a stack stack int size 構造器 stack stack bool stack isempty bool stack isfull void stack push int data int stack pop int main data data i...