在c#中定義類時,常常不需要定義相關的建構函式和析構函式,因為基類system.object提供了乙個預設的實現方式。但是,如果需要,可以提供自己的建構函式和析構函式,以便初始化物件和清理物件。
使用下述語法把乙個簡單的建構函式新增到類中:
class myclass
public myclass()
這個建構函式與包含它的類同名,且沒有引數(使之成為類的預設建構函式),這是乙個公共函式,所以類的物件可以使用這個建構函式進行例項化。
也可以使用私有的預設建構函式,即這個類的物件例項不能用這個建構函式來建立:
class myclass
private myclass()
//constructor code.
最後,也可以用相同的方式給類新增非預設的建構函式,其方法是提供引數,例如:
class myclass
public myclass()
//default constructor code.
public myclass(int myint)
//nondefault constructor code (uses myint)
析構函式使用略微不同的語法來宣告。在.net中使用的析構函式(由system.object類提供)叫作finalize(),但這不是我們用於宣告析構函式的名稱。使用下面的**,而不是重寫finalize():
class myclass
~myclass()
//destructor body.
類的析構函式有帶有~字首的類名(與建構函式的相同)來宣告。當進行垃圾**時,就執行析構函式中的**,釋放資源。在呼叫這個析構函式後,還將隱式地呼叫基類的析構函式,包括system.object根類中的finalize()呼叫。這個技術可以讓.net framework確保呼叫finalize(),因為重寫finalize()是指基類呼叫需要顯示地執行,這是有潛在危險的。
建構函式的執行序列
如果在類的建構函式中執行多個任務,把這些**放在乙個地方是非常方便的。使用乙個方法就可以把**放在乙個地方,而c#提供了乙個更好的方式。任何建構函式都可以進行配置,在執行自己的**前呼叫其他建構函式。
在討論建構函式前,先看看在預設情況下,建立類的例項時會發生什麼情況。在開發過程中,物件常常並沒有按照希望的那樣執行,而是在呼叫建構函式時出現錯誤。這常常是因為類繼承結構中的某個基類沒有正確例項化,或者沒有正確地給其類建構函式提供資訊。理解在物件生命週期的這個階段發生的事情,將更容易解決這類問題。
為了例項化派生的類,必須例項化它的基類。而要例項化這個基類,又必須例項化這個基類的基類,這樣一直到例項化system.object為止。結果是無論使用什麼建構函式例項化乙個類,總是要先呼叫system.object.object()。
如果對乙個類使用非預設的建構函式,預設的情況是呼叫基類的預設建構函式(這裡與原書不一致。原書的內容是:"如果對乙個類使用非預設的建構函式,預設的情況下是在其基類上使用匹配於這個建構函式簽名的建構函式。如果沒有找到這樣的建構函式,就使用基類的預設建構函式(根類system.object總是要使用預設的建構函式,因為這個類沒有非預設的建構函式)。")。考慮下面的物件結構:
class
mybaseclass
public mybaseclass(int i)
}class
myderivedclass: mybaseclass
public myderivedclass(int i)
public myderivedclass(int i, int j)
}注:下面的內容與原書有差異,略有修改。我的**是在.net 3.5環境下執行。
如果以下面的方式例項化myderivedclass:
myderivedclass myobj = new myderivedclass();
則事件的順序如下:
另外,如果使用下面的語句:
myderivedclass myobj = new myderivedclass(4);
則事件的順序如下:
最後,如果使用下面的語句:
myderivedclass myobj = new myderivedclass(4,8);
則事件的順序如下:
使用這個順序把可以使用int i引數的**放在mybaseclass(int i)中,即myderivedclass(int i,int j)建構函式要做的工作比較少,只需處理int j引數(假定int i引數在兩種情況下有相同的含義,雖然事情並非如此,但實際上我們常常做這樣的安排)。只有願意,c#就可以指定這種操作。
為此,只需在派生類的建構函式定義中指定所使用的基類的建構函式,如下所示:
class
myderivedclass: mybaseclass
public myderivedclass(int i)
public myderivedclass(int i, int j):base(i)
}其中,base關鍵字指定.net例項化過程中使用基類中匹配指定簽名的建構函式。
也可以使用這個關鍵字指定基類建構函式的字面值,例如使用myderivedclass的構造函式呼叫mybaseclass非預設的建構函式:
class
myderivedclass: mybaseclass
public myderivedclass(int i)
public myderivedclass(int i, int j):base(i)
}myderivedclass myderivedobject = new
myderivedclass();
這段**將執行下述系列:
除了base關鍵字外,這裡還可以使用另乙個關鍵字this。這個關鍵字指定在呼叫指定的建構函式前,.net例項化過程中對當前類使用非預設的建構函式。例如:
class
myderivedclass: mybaseclass
public myderivedclass(int i)
public myderivedclass(int i, int j):base(i)
}myderivedclass myderivedobject = new
myderivedclass();
這段**將執行下述系列:
唯一的限制是使用this或base關鍵字只能指定乙個建構函式。但是,如上乙個示例所示,這並不是乙個嚴格的限制,因為我們仍可以構造相當複雜的執行序列。
C 的構造和析構函式入門
上課的時候老師雖然講過一點點構造和析構,但是記憶不深刻而且當時也沒有什麼概念,總是覺得構造和析構是乙個很高深的東西,現在自學整理一下構造和析構的簡單知識點。0.構造和析構函式的作用 因為類的資料成員是不能再宣告類時初始化的,所以提供了建構函式來完成初始化,它可以自動完成,在建立物件的時候自動完成,不...
C 建構函式和析構函式
1.建構函式是類的一種特殊方法,每次建立類的例項都會呼叫它。在建立乙個類的例項時,建構函式就像乙個方法一樣被呼叫,但不返回值。語法格式 訪問修飾符 類名 特性 1 其名字必須與類名相同,例如 public class myclass 2 不能被直接呼叫,必須通過new運算子來 呼叫。publiccl...
C 建構函式和析構函式
建構函式 class rectangel rectangel int l,int w 這是帶引數的建構函式,建構函式都是沒有返回值,並且和該類同名 int area 這是另一種形式的內聯函式,把宣告和定義寫在一起的也是內聯函式 private int length int width 析構函式 cl...