直接上例子,通过例子来学习知识,是我一贯的做法,呵呵。
//爷爷类 public class GrandfatherClass { public GrandfatherClass() { Console.WriteLine("Constructor of GrandfatherClass"); } public GrandfatherClass(string from) { Console.WriteLine("Constructor of GrandfatherClass:{0}", from); } } //父亲类 public class FatherClass:GrandfatherClass { public FatherClass() { Console.WriteLine("Constructor of FatherClass"); } public FatherClass(string from) { Console.WriteLine("Constructor of FatherClass:{0}", from); } } //小霸王类,我是小霸王,腰里别只鸡 public class MeClass : FatherClass { public MeClass() { Console.WriteLine("Constructor of MeClass"); } public MeClass(string from) { Console.WriteLine("Constructor of MeClass:{0}", from); } } static void Main(string[] args) { //类实例化 Console.WriteLine("类实例化,调用无参构造函数:"); MeClass me = new MeClass(); Console.WriteLine(); //类实例化,含参数 string from = "tiana0"; Console.WriteLine("类实例化,调用有参构造函数:"); MeClass me1 = new MeClass(from); }
运行代码,得到以下结果:
通过对运行结果的分析,可以得出以下结论:
子类会从下往上(本例中的MeClass到FatherClass,再到GrandfatherClass)延继承关系依次调用父类的无参构造函数。记住:是无参的构造函数哦。所以,在MeClass类实例化时,不管自己调用的构造函数是有参的还是无参的,父类被调用的构造函数永远是无参的。所以两次实例化时,父类被调用的都是无参的构造函数。当然,执行时,就应该是从上往下(先是GrandfatherClass,再是FatherClass,最后才是MeClass)依次来执行构造函数的,所以结果中,父类的构造函数先于子类的构造函数被执行。这有点像:一旦有了难处,孩子就会去找父亲,父亲搞不定时,就得找德高望重的老爷子,老爷子搞定了,父亲自然也能搞定了,父亲搞定了,儿子还能搞不定它或者她(开个玩笑而已,比喻不当也别见怪)。
接下来,再做个小实验,将前面代码中的以下部分注释掉:
//public FatherClass() //{ //Console.WriteLine("FatherClass Constructor:FatherClass()"); //}
你会发现,出现了编译错误,错误提示如下:
FatherClass不包含采用“0”个参数的构造函数。
为什么呢,哥们,快快道来。别急,在揭晓答案之前,还得做个实验,实验同样简单,首先取消对刚才代码的注释,再接着将以下部分注释掉:
//public FatherClass(string from) //{ //Console.WriteLine("FatherClass Constructor:FatherClass({0})", from); //}
你会发现,编译代码一切正常。
那到底是为什么呢(小沈阳说:为什么呢?),原因其实在前面已经解释过了,类会从下往上延继承关系依次调用父类的无参构造函数。当FatherClass的无参构造函数被注释后,这条通道自然就不存在了,当然会报错的嘛,至于FatherClass的有参构造函数注不注释掉,没有任何影响,因为调用的是无参的构造函数哦(再来哦~~一次)。
先写到这里,要睡觉了,亲。
补上一句,你还可以单步调试,跟踪代码走向,同样会得出以上结论。