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