为何派生类需向基类构造函数传值且基类构造先执行?
咱们先看你贴的这段C#代码:
namespace Sample { public class Program { static int x; public Program(int Y) { x = Y; Console.WriteLine("one value base class constructor called"); } static void Main(string[] args) { Program prog = new s(10); Console.ReadKey(); } } public class s: Program { public s(int k):base(10) { Console.WriteLine("derived class constructor called"); } } }
你提到的两个核心问题,我给你拆解清楚背后的底层逻辑:
1. 基类构造函数为何优先调用?
这得从面向对象继承的本质说起:派生类是基于基类的“扩展”,它继承了基类的所有非私有成员(字段、方法等)——这些是派生类能正常工作的基础。
打个比方:你要建一栋带露台的房子,派生类是露台,基类是房子主体。你总不能先建露台再建房子主体吧?露台得依附在主体上才能存在。同理,派生类的实例必须先让基类把自己的成员初始化好,派生类才能安全地使用这些成员(比如在派生类构造函数里调用基类的方法、访问基类的字段)。
从CLR(.NET运行时)的执行机制来说,当你创建派生类实例时,执行流程是:
- 先调用基类的构造函数,完成基类部分的初始化
- 再调用派生类的构造函数,完成派生类自身的扩展部分初始化
这样才能保证整个对象的完整性,避免出现“派生类想用基类的成员,但基类还没初始化”的错误。
2. 基类有带参构造时,派生类为何必须向其传值?
这里要先搞清楚C#构造函数的一个默认规则:如果一个类没有显式定义任何构造函数,编译器会自动帮它生成一个无参的默认构造函数;但如果类显式定义了带参构造函数,编译器就不会再生成默认的无参构造了。
回到你的问题:你的基类Program只定义了带参构造Program(int Y),所以编译器没有生成无参构造。这时候,派生类s在创建实例时,必须明确告诉编译器“我要调用基类的哪个构造函数来初始化基类部分”——因为基类没有无参构造可以默认调用了。
再用房子的例子:如果基类(房子主体)的建造必须要你提供“地基宽度”这个参数(带参构造),你不提供的话,施工队(编译器)根本不知道怎么建主体,自然会报错。
你看到的报错there is no argument given that corresponds to the required formal parameter,本质就是编译器找不到基类的无参构造,而你又没显式指定调用带参构造,它没法完成基类部分的初始化,所以只能报错提示你。
内容的提问来源于stack exchange,提问作者Nikhil

