构造函数的调用顺序是先调用System.Object,再按照层次结构由上向下(基类=》派生类)进行,直到到达编译器要实例化的类为止。在此过程中,每个构造函数都初始化自己类中的字段。编译器先自下而上查找构造函数,然后再自上而下地执行。
以下通过示例说明派生类的构造函数是如何执行的。
1.基类和派生类都未显示定义构造函数
执行GenericCustomer customer = new Nevermore60Customer();语句时,编译器首先找到试图实例化的类的构造函数即Nevermore60Customer 类的默认构造函数,默认Nevermore60Customer 构造函数首先要做的是为其直接基类GenericCustomer运行默认构造函数,然后GenericCustomer构造函数为其直接基类System.Object运行默认构造函数。而System.Object没有任何基类,所以它的默认构造函数直接执行;接着执行GenericCustomer的默认构造函数,将name字段初始化为null;最后执行Nevermore60Customer的默认构造函数,将highCostMinutesUsed字段初始化未0,并退出。
abstract class GenericCustomer { private string name; } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; }
2.基类定义了一个无参构造函数
执行GenericCustomer customer = new Nevermore60Customer();语句,构造函数执行顺序:System.Object类的默认构造函数=》GenericCustomer类的显示无参构造函数(将name字段初始化为“<no name>”)=》Nevermore60Customer类的默认无参构造函数(将highCostMinutesUsed字段初始化为0)。
abstract class GenericCustomer { private string name; public GenericCustomer() :base() //base,调用基类的构造函数(本例中调用System.Object中的构造函数,与默认情况相同,可省略) { name = "<no name>"; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; }
注意:若把GenericCustomer类中的构造函数声明为private,则类Nevermore60Customer会产生一个编译错误。因为编译器试图为Nevermore60Customer类生成默认构造函数时,需要调用类GenericCustomer的无参构造函数,但是这个函数是类GenericCustomer所私有的,其他类无法调用。
3.基类和派生类都定义了有参构造函数
执行GenericCustomer customer = new Nevermore60Customer("LiSi");语句时,构造函数执行顺序:System.Object类的默认构造函数=》GenericCustomer类的有参构造函数(将name字段初始化为“LiSi”)=》Nevermore60Customer类的有参构造函数(什么也不做)。
abstract class GenericCustomer { private string name; public GenericCustomer(string name) { this.name = name; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; public Nevermore60Customer(string name) :base(name) { } }
注意:若类Nevermore60Customer未定义上面的有参构造函数,则类Nevermore60Customer会产生一个编译错误。因为类Nevermore60Customer生成的默认构造函数会试图调用GenericCustomer类中的无参构造函数,但它并没有这样的函数。
4.派生类中有多个构造函数
执行GenericCustomer customer = new Nevermore60Customer("LiSi");语句时,构造函数执行顺序:System.Object类的默认构造函数=》GenericCustomer类的有参构造函数(将name字段初始化为“LiSi”)=》Nevermore60Customer类中有两个参数的构造函数(将referrerName字段初始化为“None”)=》Nevermore60Customer类中有一个参数的构造函数(什么也不做)
abstract class GenericCustomer { private string name; public GenericCustomer(string name) { this.name = name; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; private string referrerName; public Nevermore60Customer(string name, string referrerName) : base(name) { this.referrerName = referrerName; } public Nevermore60Customer(string name) : this(name, "<None>") { } }
参考来源:《C#高级编程(第9版)》