虚函数和重载
面试必考。。。。。
1 #include <stdio.h> 2 class CBase 3 { 4 public: 5 virtual void f(int x) 6 { 7 printf("CBase::f 函数打印:整数%d\n",x); 8 } 9 10 void g(float x) 11 { 12 printf("CBase::g 函数打印:浮点小数%f\n",x); 13 } 14 }; 15 16 // 继承类 CDerived 17 class CDerived:public CBase 18 { 19 public: 20 void f(int x) 21 { 22 printf("CDerived::f 函数打印:整数%d\n",x); 23 } 24 public: 25 26 void g(float x) 27 { 28 printf("CDerived:g 函数打印:浮点小数%f\n",x); 29 } 30 }; 31 32 33 void main() 34 { 35 36 CDerived DerivedObj; 37 DerivedObj.f(3); 38 DerivedObj.g(6.0f); 39 40 CBase* pBaseObj = &DerivedObj; 41 pBaseObj->f(3); // 此处是指针访问 42 pBaseObj->g(6.0f); 43 }
输出结果为: CDerived::f 函数打印:整数3 CDerived:g 函数打印:浮点小数6.000000 CDerived::f 函数打印:整数3 CBase::g 函数打印:浮点小数6.000000 |
如果将继承类对象转换为基类对象去调用 f 和 g ,就不一定调用继承类本身的函数。因为基类CBase 的函数 f 为 virtual 虚函数,而继承类 CDerived 又重载了该函数,于是基类的函数 f 【被覆盖】掉,从而 CBase 类的函数实际是 CDerived::f 和 CBase::g。所以,利用转换为基类的对象 *pBaseObj 调用 f函数,仍然是继承类本身定义的函数;但调用 g 函数,则是基类的 g 函数,而不是继承类本身的函数g。这种调用是需要提防的,可能产生混乱。
由此可见,如果一个类的函数希望做的灵活一些,允许继承类的重载函数修改它,最好将它声明为 virtual 虚函数。一个函数一经声明为 virtual 函数,它在继承类中的重载函数,也是虚函数,不必再用virtual 进行修饰。
此外,如果在虚函数的声明之后加上 "=0" 的标记,函数就成为纯虚函数。一个类包含纯虚函数的定义,该类称为抽象类。抽象类不能创建对象,作为继承类的【接口】规范,要求继承类必须提供一个纯虚函数的具体实现,否则产生编译错误。
如下是纯虚函数的一般定义:
virtual 函数返回值类型 函数名( 参数列表 ) =0;
一句话总结:虚函数是为了实现【多态】; 纯虚函数是为了实现【接口】;
暂时只讨论这么多,后续还会再补充........
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?