C#中继承和构造函数
一个类继承自另外一个类,他们的构造函数改怎么办?
首先必须先声明:构造函数是不能继承的
我们先看一段代码:第一段代码没有构造函数,第二段有一个,第三段有两个。从他们的MSIL可以看出,有几个构造函数就有几个.ctor的il函数。
即使你没有构造函数,编译器也会调用一个空的构造函数。让我们仔细瞧瞧MSIL代码:
我们可以看到每个IL中都有 instance void [mscorlib]System.Object::.ctor()
由此我们可以得出。不管你有几个构造器,你都必须执行父类的构造函数,才能执行当前构造函数;同样对于继承,必须先实现父类的构造函数,才能执行自己的.ctor
如果我们写一个空的构造函数 public class someType{ public someType(){ } }
就是public class someType{ public someType():base(){ } } 。这种方法是调用(基)类中其他的构造器
(方法一,二 都只有一个.ctor)(方法三:有两个.ctor)
static void Main(string[] args) { Console.WriteLine("nihao"); }
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
class Program { private Int32 i; public Program(Int32 i) { this.i = i; } static void Main(string[] args) { Console.WriteLine("nihao"); } }
.method public hidebysig specialname rtspecialname
instance void .ctor(int32 i) cil managed
{
// 代码大小 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: stfld int32 MSIL.Program::i
IL_000f: nop
IL_0010: ret
} // end of method Program::.ctor
class Program { private Int32 i; private Int32 j; public Program(Int32 i) { this.i = i; } public Program(Int32 i, Int32 j) { this.i = i; this.j = j; } static void Main(string[] args) { Console.WriteLine("nihao"); } } .method public hidebysig specialname rtspecialname instance void .ctor(int32 i, int32 j) cil managed { // 代码大小 24 (0x18) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldarg.1 IL_000a: stfld int32 MSIL.Program::i IL_000f: ldarg.0 IL_0010: ldarg.2 IL_0011: stfld int32 MSIL.Program::j IL_0016: nop IL_0017: ret } // end of method Program::.ctor .method public hidebysig specialname rtspecialname instance void .ctor(int32 i) cil managed { // 代码大小 17 (0x11) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldarg.1 IL_000a: stfld int32 MSIL.Program::i IL_000f: nop IL_0010: ret } // end of method Program::.ctor
首先我们看看一个关于this()/base() 也就是本构造器调用其他构造器的例子,注意调用其他构造器在前,再执行自己的代码
class Program { private Int32 i; private Int32 j; private string m; public Program() //初始化所有变量 { this.i = 1; this.j = 2; this.m = "nimei"; } public Program(Int32 i):this() //构造单个变量 { this.i = i; } public Program(Int32 j): this() { this.i = j; } public Program(string m): this() { this.m = m; } static void Main(string[] args) { Console.WriteLine("nihao"); } }
三、接下来贴出搞了我一下午的一个例子。在上篇博客中讲到用范型实现一个链表。但是那种实现方式中,链表的每个值必须都是同一个类型,本例中实现任意类型
直接贴代码,下面解释
public class baseNode { protected baseNode bNode; public baseNode(baseNode bn) { this.bNode = bn; } } public class Node2<T>:baseNode { private T _data; public Node2(T data):this(data,null) //:base(null) 注意在构造之前要实现父类的构造函数 { this._data = data; } public Node2(T data,baseNode bNode):base(bNode) { this._data = data; } public override string ToString() { return _data.ToString() + (bNode != null ? bNode.ToString() : null); } } public class LeaderFunction2 { public void function() { baseNode node = new Node2<char>('A'); node = new Node2<string>("B", node); node = new Node2<Int32>(3354435, node); node = new Node2<char>('D', node); node = new Node2<char>('E', node); Console.WriteLine(node.ToString()); Console.ReadKey(); } }
这个例子理解了一下午,搞不懂其内部机制,想用MSIL解释,看到那些伪汇编头都大,主要是由于自己的基础知识不扎实啊!
本例中:第一,注意继承要实现父类的构造
第二,为什么这样写可以实现:
其实还是和之前的一样,虽然到了最后node指向最后一个 NOde2对象,但是之前的对象都没有销毁,地址保存在下个node2中的basenode.bNodeN中。