一、完整代码
using System;
class Program
{
static void Main(string[] args)
{
// 调用子类【双参构造】
Student s2 = new Student(10,"张三");
}
}
// 父类
public class People
{
public string Name { get; set; }
// 父类无参构造
public People()
{
Console.WriteLine("1 父类的无参数构造函数");
}
// 父类有参构造
public People(string name)
{
Name = name;
Console.WriteLine("2 父类带参数的构造函数");
}
}
// 子类继承 People
public class Student:People
{
public int Age { get; set; }
// 子类无参构造:默认调用父类无参 base()
public Student():base()
{
Console.WriteLine("3子类的无参数构造函数");
}
// 子类有参构造:base(n) 主动调用父类【有参构造】
public Student(int age, string n) : base(n)
{
Age = age;
Console.WriteLine("4子类带参数的构造函数"+Name);
}
}
二、运行结果
2 父类带参数的构造函数
4子类带参数的构造函数张三
三、执行流程拆解(必考)
执行代码:new Student(10,"张三")
- 进入子类双参构造 Student(int age, string n)
- 优先执行末尾 :base(n),将字符串传给父类
- 触发父类有参构造函数,给 Name 赋值、打印语句
- 父类构造执行完毕,退回子类构造函数体
- 执行子类内部代码,打印子类语句 + 输出赋值后的 Name
三、2. 核心执行规则(必考)
1. 继承构造铁律
创建子类对象,优先执行父类构造函数,再执行子类构造函数,遵循「先父后子」的
固定顺序,无法跳过父类初始化。
2. base 关键字作用
- :base():调用父类无参构造,子类无参构造默认自带,可省略不写
- :base(参数):手动指定调用父类有参构造,必须手写,可给父类属性传值
- base调用语句优先级最高,必须在子类构造函数方法体执行前运行
3. 本次代码执行流程
- 执行 new Student(10,"张三"),进入子类双参构造
- 优先执行 base(n),触发父类有参构造,给Name赋值并打印信息
- 父类构造执行完毕,返回执行子类构造方法体
- 打印子类信息,输出赋值后的父类属性Name
4 . 隐藏默认机制
如果子类构造不写 base,默认等价于 :base(),自动找父类无参构造。
四、重点易错知识点
- 子类任意构造函数,默认都会隐式调用 base()(父类无参构造)
- 只要父类手写了有参构造,系统自动删除默认无参构造
- 若父类只手写有参构造、无无参构造,子类会直接报错,因为默认找不到无参base
- base 调用必须在构造函数后缀,必须最先执行
- 想要调用父类有参构造,必须手动书写 base(参数) 覆盖默认规则
- base关键字仅能在构造函数后缀使用,普通方法无法调用base()
五、两种实例化方式对比
-
new Student() ➜ base() → 调用父类无参构造 → 执行子类无参构造
-
new Student(10,"张三") ➜ base(n)→ 调用父类有参构造 → 执行子类有参构造
六、简答题满分模板
问:继承中构造函数的执行顺序与base的作用?
实例化子类对象时,优先执行父类构造函数完成父类初始化,再执行子类构造函数。base关键字用于子类构造函数中调用父类构造函数,无参base默认调用父类无参构造,带参base可主动调用父类有参构造,实现父类数据初始化。
------------------------五大访问修饰符------------------------
一、五个修饰符对应字段
public class People
{
public int a = 10; // 公共
private int b = 20; // 私有
protected int c = 30; // 受保护
protected internal int d = 30; // 受保护内部
internal int e = 30; // 内部
}
二、五大场景判断标准(考试唯一标准答案)
判断五个维度:
-
本类内部能否访问
-
同项目子类能否访问
-
同项目外部实例能否访问
-
跨项目子类能否访问
-
跨项目外部实例能否访问
三、终极权限对照表(100%贴合你代码实测)
| 修饰符 | 本类内部 | 同项目子类 | 同项目实例 | 跨项目子类 | 跨项目实例 | 核心总结 |
|---|---|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ | ✅ | 完全公开,所有地方都能访问 |
| private | ✅ | ❌ | ❌ | ❌ | ❌ | 仅当前类内部可用,最私有 |
| protected | ✅ | ✅ | ❌ | ✅ | ❌ | 只给子类用,对象实例永远点不出来 |
| internal | ✅ | ✅ | ✅ | ❌ | ❌ | 锁死当前项目,出项目彻底失效 |
| protected internal | ✅ | ✅ | ✅ | ✅ | ❌ | 同项目随便用,跨项目只给子类用 |
四、两段代码实测结果精讲
1、同项目测试(_7属性访问修饰符)
子类 Man 和父类 People 在同一个项目
// 同项目子类中
Console.WriteLine(a); // public ✅
// Console.WriteLine(b); // private ❌
Console.WriteLine(c); // protected ✅
Console.WriteLine(d); // protected internal ✅
Console.WriteLine(e); // internal ✅
结论:同项目下 internal 和 protected 权限几乎一样,子类都能访问。
2、跨项目测试(_8测试7的)
类 Woman 在新项目,引用原项目的 People
// 跨项目子类中
Console.WriteLine(a); // public ✅
Console.WriteLine(c); // protected ✅
Console.WriteLine(d); // protected internal ✅
// Console.WriteLine(e); // internal ❌ 跨项目失效
这是考试最大考点!!
internal 跨项目完全不能用
protected 跨项目子类依然可用
五、外部对象实例能点出哪些?
People p = new People();
// 同项目实例
p.a ✅
p.d ✅
p.e ✅
// p.b ❌ private
// p.c ❌ protected 禁止实例访问
死规则:protected 永远不能被对象实例访问!
六、最易混淆两组区别(必考简答题)
1. protected 和 internal 的区别
-
protected:权限看「是否是子类」,跨项目子类照样能用
-
internal:权限看「是否同项目」,跨项目谁都不能用
2. internal 和 protected internal 的区别
-
internal:跨项目彻底失效
-
protected internal:跨项目子类依然可以使用
七、满分背诵口诀
-
public 全开放,哪都能用
-
private 自家藏,谁都别想
-
protected 子类享,实例摸不着
-
internal 锁本项目,出界就报废
-
pro-in 最强组合,本子随便、跨子也可
八、简答题标准答案(直接默写)
1. internal 和 protected 的区别?
internal 修饰的成员仅限当前程序集(项目)内访问,跨项目无法使用;protected 修饰的成员仅限本类和所有子类访问,支持跨项目子类继承访问,但不允许外部对象实例访问。
2. protected internal 是什么权限?
是两种权限的并集,同项目中所有类和实例均可访问,跨项目仅允许子类继承访问,外部实例无法访问。