基类指针、虚纯虚函数、多态性、虚析构
多态
基类指针
// 父类指针可以 new 一个子类对象
Human *pman = new Man();
Human *pwman = new Wonan();
抛出问题:父类指针没有办法调用子类的成员函数,那么你为什么还让父类指针 new 一个子类对象呢?
下面与虚函数搭配
虚函数(动态绑定)
我们只定义一个对象指针,就能够调用父类,以及各个子类的同名函数? ===> 有,这个对象指针,它的类型必须是父类类型
对这个函数有要求:
- 父类中,函数声明之前要加 virtual 声明成虚函数
- 一旦某个函数(在基类)被声明成了虚函数,那么所有派生类(子类)中同名函数都是虚函数
Human *phuman = new Men();
phuman->eat(); // 调用的是 Men 类的 eat 函数
delete phuman; // new 的对象使用完之后要 delete,防止内存泄漏
phuman = new Women();
phuman->eat(); // 调用的是 Women 类的 eat 函数
delete phuman;
phuman = new Human();
phuman->eat(); // 调用的是 Human 类的 eat 函数
delete phuman;
override
注意:为了避免你在子类中写错虚函数,在 C++11 中,你可以在函数声明这里增加一个 override 关键字
这个关键字在 "子类" 中,而且是子虚函数专用
override就是用来说明派生类中的虚函数,你用了这个关键字之后,编译器就会认为你这个 函数就是覆盖了父类中的同名函数。
只有虚函数才存在子类可以覆盖父类中同名函数的问题,那么编译器就会在父类中找同名同参的虚函数,如果没找到,编译器就会报错、
final
final 也是虚函数专用,是用在父类,如果我们在父类的函数声明中加了 final,那么任何尝试覆盖该函数的操作都将引发错误。
virtual void eat() final;
多态性
系统内部实际上是要查一个虚函数表,找到 eat() 的入口地址,从而调用父类或者子类的 eat() 函数,这就是运行时期的多态性
纯虚函数【类似 Java 中的接口 interface】===> 函数原型后增加 = 0
纯虚函数:没有函数体,只有一个函数声明
virtual void eat() = 0;
是在基类中声明的虚函数,但是它在基类中没有定义,但是要求任何派生类都要定义该虚函数自己的实现方法
注意:一旦一个类中有纯虚函数了,那么你就不能生成这个类的对象了【Java 中 interface 不能生成对象】
抽象类不能用来生成对象,主要目的用来统一管理子类对象
基类的析构函数一般写成虚函数(虚析构函数)
// 1. 声明一个 men 对象
Men men;
// 2. 写法2:使用 new
Men *pmen = new Men();
delete pmen; // 自己 new 的对象,必须使用 delete 调用析构函数
有一个问题
Human *phuman = new Men(); // 父类指针指向 子类对象
delete phuman; // 没有执行子类的析构函数
结论:用基类指针 new子类的对象,在 delete 的时候,系统不会调用派生类的析构函数,这肯定就有问题了
解决方式:
- 父类的析构函数写成虚函数
- 继承时候使用 public
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2023-10-26 判断周围8个方向的位置
2023-10-26 常用在线画图工具