当前位置: 首页 > news >正文

深入解析C#多态性:基类引用、虚方法与覆写机制

基类引用的本质

在C#面向对象编程中,派生类对象由基类部分和扩展部分组成。通过基类引用访问派生类对象时,实际是在进行「观察视角」的转换:

MyDerivedClass derived = new MyDerivedClass(); 
MyBaseClass mybc = (MyBaseClass)derived;  // 视角转换 
  • 🔑 基类引用只能访问继承链中的成员
  • ⚠️ 无法通过基类引用访问派生类新增成员(如示例中的var1)
  • 🖼️ 内存布局:基类部分始终位于对象内存起始位置

虚方法的多态魔法

当使用virtual和override组合时,将实现真正的多态行为:

// 基类定义 
virtual public void Print() { ... }// 派生类覆写 
override public void Print() { ... }

✅ 调用链规则:

  • 通过基类引用调用时,自动寻找最高派生版本的实现
  • 实际执行的是运行时类型的方法(动态绑定)

🚫 常见错误:

  • 覆写方法访问级别不一致
  • 试图覆写非虚方法
  • 忘记override使用new导致隐藏而非覆写

多层继承中的覆写策略

在三级继承体系中,覆写行为呈现链式反应:

class Base { virtual void Print() }
class Derived : Base { override void Print() }
class SecondDerived : Derived { ... }
修饰符调用结果内存表现
override执行最顶层派生类方法法表指针指向最新实现
new停留在当前继承层级的实现创建独立方法槽,与基类实现并存

实战对比:override vs new

通过代码实验验证不同修饰符的效果差异:

// 情况1:使用override 
SecondDerived.Print => "SecondDerived"
mybc.Print => "SecondDerived"// 情况2:使用new 
SecondDerived.Print => "SecondDerived" 
mybc.Print => "Derived"

📊 执行原理图解:

  • override形成方法调用链
  • new创建独立方法分支
  • 虚方法表(vtable)的结构差异

扩展应用:属性与索引器的覆写

多态机制不仅限于方法,同样适用于属性:

class Base {virtual int MyProp { get { return 5; } }
}class Derived : Base {override int MyProp { get { return 10; } }
}

📌 属性覆写需保持:

  • 相同的名称和返回类型
  • 一致的访问器签名(get/set)

💡 索引器覆写同理:

  • 保持参数列表一致
  • 使用virtual/override修饰

最佳实践指南

合理设计虚方法:

  • 将可能变化的逻辑声明为virtual
  • 保持基类方法的稳定性

谨慎使用new修饰符:

  • 仅当需要刻意隐藏基类实现时使用
  • 添加XML注释说明隐藏意图

多态设计原则:

  • 遵循里氏替换原则
  • 通过抽象基类定义契约
  • 使用protected保护核心实现

关键理解:多态的本质是通过类型引用与对象实体的分离,实现「同一接口,多种实现」的面向对象特性。掌握虚方法机制,能显著提升代码的扩展性和可维护性。

http://www.xdnf.cn/news/744481.html

相关文章:

  • 字符串索引、幻读的解决方法
  • Pytorch---ImageFolder
  • C++ 的四种强制类型转换:static_cast、dynamic_cast、const_cast 和 reinterpret_cast
  • MIT 6.S081 2020 Lab6 Copy-on-Write Fork for xv6 个人全流程
  • 修改 vscode 左侧导航栏的文字大小 (更新版)
  • Cursor奇技淫巧篇(经常更新ing)
  • # STM32F103 串口打印配置(HAL库)
  • foundationpose位姿检测环境搭建与数据集制作
  • Android任务栈管理策略总结
  • 蓝桥杯 盗墓分赃2
  • Deepin 23.10安装Docker
  • Go语言中的布尔类型详解
  • 截面动量策略思路
  • 内存管理 : 04段页结合的实际内存管理
  • Muduo网络库重点技术详解
  • tomcat服务器以及接受请求参数的方式
  • Java网络编程实战:TCP/UDP Socket通信详解与高并发服务器设计
  • uniapp uni-id Error: Invalid password secret
  • Linux531rsync定时同步 再回忆
  • 智能测试新范式:GenAI 与 Playwright MCP 如何重塑 QA 流程
  • 【Ubuntu】摸鱼技巧之虚拟机环境复制
  • C#WinForm程序时方法很多时Form.cs文件会很长,如何分别写入多个文件,partial class的作用体现出来了。
  • 矩阵快速幂算法快速上手
  • 极大似然估计例题——正态分布的极大似然估计
  • 尚硅谷redis7 99 springboot整合redis之连接集群
  • AppTrace 视角下 App 一键拉起:提升应用转化率的高效方案​
  • 使用Gemini, LangChain, Gradio打造一个书籍推荐系统 (第四部分)
  • 自动驾驶系列—Monocular 3D Lane Detection for Autonomous Driving
  • 【Web API系列】WebTransportSendStream接口深度解析:构建高性能实时数据传输的基石
  • Python实现P-PSO优化算法优化循环神经网络LSTM分类模型项目实战