[转]默认构造函数的作用
構造函數主要用來初始化對象。它又分為靜態(static)和實例(instance)構造函數兩種類別。大家應該都了解如果來寫類的構造函數,這里只說下默認構造函數的作用,以及在類中保留默認構造函數的重要性。實際上,我說錯了。正確的說法是:以及在類中保留空參數構造函數的重要性。
我們來寫一個類A,代碼如下:
public class A
{
?? public int Number;?????? //數字
?? public string Word;?????? //文本
}
//在Test類中實例化
public class Test
{
??? static void Main()
{
????? ?A a = new A();?//實例化,A()即為類A的默認構造函數
??? ?Console.WriteLine(“Number = {0}"nWord = {1}”,a.Number,a.Word);
?? ????Console.read();
}
}
輸出的結果是:
Number = 0
Word =
在上列示例中,我們并沒有在A類中明確的寫出構造函數,當我們沒有提供任何構造函數時,C#自動為類提供了一個默認構造函數,其格式為:
public A()
{
?? //空白的方法體
}
這個默認構造函數看起來似乎根本沒什么作用,沒有接收任何輸入參數,方法體也是個空的。那么它真的是無所事事,可有可無的一個東西嗎?我們回想下前面所講的構造函數的主要作用,對,它主要用來初始化對象。看下輸出結果,int類型的Number被初始化為默認值0,string類型的Word被初始化為默認值空白字符,這些工作都是由看似沒起作用的默認構造函數所完成的。
很快,A類的設計讓我們并不滿意,我們加強了它的能力,自己提供了構造函數:
public class A
{
??? public int Number;?????
??? public string Word;?????
??? public A(int number,string word)
{
?? Number=number; ???//標記1
?? Word=word;???????//標記2
}
}
//Test類也重新設計
public class Test
{
static void Main()
{
??? ????A a = new A(100,”一百”);?//調用了新的帶參數構造函數
??? ??Console.WriteLine(“Number = {0}"nWord = {1}”,a.Number,a.Word);
?? ?????Console.read();
}
}
輸出結果:
Number = 100
Word = 一百
運行很順利,結果正確。當我們提供了構造函數時,C#認為我們應該是意識到、并且有能力來做好類的初始化工作,于是它將默認的構造函數撤銷,將控制權交到了我們手里。我們自己的構造函數能勝任默認構造函數的工作嗎?帶著懷疑,我們做個嘗試,將類A構造函數的方法體清除,即注釋掉標記1和2行,重新運行,輸出的結果是:
Number =0
Word =
這個結果和調用默認構造函數的結果是一樣的,這證明我們自己提供的構造函數能擔當默認構造函數的工作。
不久以后,業務進一步擴展,我們要新構一個類,這個類繼承自類A,我們把它稱為類B:
public class A
{
?? ?public int Number;?????
??? public string Word;?????
??? public A(int number,string word)
{
?? Number=number;??
?? Word=word;????
}
}
public class B:A
{
??? public string Name;?? //增加一個成員
??? public B(int number,string word)
{
?? Number = number;
?? Word = word;
}
}
//修改Test類
public class Test
{
?? static void Main()
{
?????? B b = new B(100,”一百”);
?????? Console.WriteLine(“Number = {0}"nWord = {1}”,b.Number,b.Word);
?????? Console.Read();
??? }
}
運行后出錯,錯誤信息是:“A”方法沒有采用“0”個參數的重載。為什么會這樣呢?看起來我們并沒有什么錯誤呀。A類提供了構造函數,B類也提供了構造函數。你滿腹委屈,含淚望著比爾蓋茨。老比怒目圓睜,啪的給你一巴掌:“A類還沒構造好,你讓我怎么給你構造B類!”。A類?構造?A類還要構造嗎?你莫名奇妙了。
事實上,B類要完成構造,必須先完成A類的構造。當我們采用:
public B(int number,string word)
來構造B類時,由于沒有明確指明繼承的構造方法,C #默認我們繼承自默認構造函數。
public B(int number,string word):base()
采用這條構造函數時,C# 先調用類A的默認構造函數base()完成基類的構造,然后調用B類的構造函數完成針對B類構造的剩余工作。嘗試修改上面的相應代碼段為:
//在類A中添加一個空參構造函數
public class A
{
???? ……
???? public A()
???? {
???????? Number =1;
???????? Word=”空參構造”;
???? }
???? …….
}
//將類B構造函數改為繼承A類空參構造
public B(int number,string word):base()
實際上,我是多此一舉了,public B(……):base()與public B(……)是一樣的,未顯式指明構造函數的繼承體時,C#就默認為base()。
輸出結果
Number=100
Word = 一百
注意看我們給A類添加的空參構造函數,我們在方法體內給Number賦值1,給Word賦值“空參構造”。然而從輸出結果看,這些賦值都被覆蓋了。這就說明,base()在前,而后才是public B(…..)。
回頭來看我們那個錯誤的例子。遺憾的是,我們在類A中自己提供了構造函數,這導致A類的默認構造函數消失了,當B類從A類繼承默認構造函數時,找不到入口了,這就導致了如上的錯誤。如果要避免錯誤,有兩種方法:1、在A類中添加一個無參數的構造函數。2、B類構造函數顯式繼承A類的構造函數。
事情已經解釋的很清楚了,不過也許還有個小問題,就是:在B類中,我們提供了一個和A類構造函數結構相同的構造函數,為什么C#不能自動識別,自動繼承呢?
道理很簡單,C#不能靠猜測來判斷我們提供的參數究竟是要用作初始化基類還是繼承類。還是來看一個例子:
public class A
{
?? public int Number;
?? public string Word;
??? public A(int number,string word)
??? {
??????? Number = number;
??????? Word = word;
??? }
}
public class B:A
{
??? public string Name;
??? public B(int number,string word,string name):base(number,word)
??? {
??????? Number = number;
??????? Word = word;
??????? Name = name;
??? }
}
public class Test
{
??? static void Main()
??? {
???? ???B b = new B(100,”一百”,”初始化B的參數”);
??????? Console.WriteLine(“Number = {0}"nWord = {1}"nName = {2}”,
????????????? b.Number,b.Word,b.Name);
??????? Console.Read();
}
}
輸出結果是:
Number = 100
Word = 一百
Name = 初始化B的參數
注意在B類的構造函數中,我們提供了三個參數,其中前兩個用于初始化A類中的成員,第三個用于初始化B類的成員。雖然父類構造函數與子類構造函數的參數數量不一樣,然而由于我們明確的指定了繼承的關系,它們很好的完成了工作。
轉載于:https://www.cnblogs.com/huikof/archive/2008/06/27/1231365.html
總結
以上是生活随笔為你收集整理的[转]默认构造函数的作用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实验——LINUX常用网络测试命令
- 下一篇: 点点历险记