
一、先看一段示例代码下面这段 C# 代码定义了一个父类ParentClass和一个继承自它的子类ChildClass并在Main方法中创建子类对象、调用同名方法。建议先自己猜一下输出顺序再往下看分析。using System; public class ParentClass { public ParentClass() { Console.WriteLine(父类构造函数。); } public void print() { Console.WriteLine(Im a Parent Class。); } } public class ChildClass : ParentClass { public ChildClass() { Console.WriteLine(子类构造函数。); } public void print(string x) { Console.WriteLine(x); } public static void Main() { ChildClass child new ChildClass(); child.print(); child.print(打印子类); } }二、运行结果编译并运行上面的代码控制台输出如下父类构造函数。 子类构造函数。 Im a Parent Class。 打印子类可以看到创建ChildClass对象时父类的构造函数先于子类的构造函数执行而child.print()调用的是从父类继承来的无参print方法child.print(打印子类)调用的则是子类自己定义的重载版本。三、继承和执行是两码事首先要说的是继承和执行是两码事。继承指子类是否具有和父类一样的类成员而不用重新定义或实现一遍。继承的目的就是重用。执行指在类的内部或外部使用这些成员的过程。换句话说继承描述的是“类与类之间的成员归属关系”执行描述的是“运行时成员如何被调用”。二者经常同时出现但概念上并不等价。四、构造函数为什么先执行父类执行构造函数是指在使用某个类时需要创建该类的对象并为这个对象的所有成员分配内存的过程。如果该类继承了某个父类那么首先就要为父类的成员分配内存自然就会先执行父类的构造函数。因此在 C# 中子类继承父类后调用子类的非静态构造函数时会默认先调用基类的无参构造函数这是一条语言规则而不是“函数继承”。函数本身是无法被继承的继承只作用于类这一层级。补充如果父类没有无参构造函数子类构造函数必须通过: base(...)显式指定要调用的父类构造函数否则编译不通过。五、关于“重写成员的内存覆盖”当子类构造时如果碰到被override重写的成员那么这个曾经在父类构造时被分配的内存地址会在子类构造时被新的地址覆盖掉。这也是为什么在父类构造函数中调用虚方法时实际执行的可能已经是子类的实现——这一点在实际开发中需要特别小心。六、小结继承解决的是成员复用问题执行解决的是成员调用问题两者不要混为一谈。创建子类对象时父类构造函数先执行子类构造函数后执行。子类默认调用父类无参构造函数父类没有无参构造函数时必须用: base(...)显式指定。方法重载print()与print(string)与继承是两回事调用哪个版本由参数列表决定。