新闻详情

新闻详情

首页 / 资讯中心 / 详情

【C++】多态——面向对象3大特性之一

发布时间:2026/9/29 10:11:04来源:尧图网络
【C++】多态——面向对象3大特性之一
为什么多态继承实现代码的复用多态实现父子函数在调用名字相同的函数时实现不同的作用分类编译时多态静态多态函数重载和函数模板运⾏时多态(动态多态)我们今天讲的多态实现条件基/父 类的指针或引用调用虚函数为什么传引用传引用或者指针不会被“切片”1.虚函数成员函数前面加上virtual就是虚函数写法继承中的virtual写法class Student : virtual public Person为了D中不会出现A的两份数据classPerson{public:virtualvoidBuyTicket(){/* TODO: 输出 买票-全价 */cout买票-全价endl;}};classStudent:publicPerson{public:// TODO: 重写 BuyTicket输出 买票-打折virtualvoidBuyTicket(){cout买票-打折endl;}};voidFunc(Person*ptr){// TODO: 通过 ptr 调用虚函数 BuyTicketptr-BuyTicket();}intmain(){Person ps;Student st;// TODO: 分别把 ps 和 st 传给 FuncFunc(ps);Func(st);return0;}2.虚函数的重写/覆盖定义父类、子类有相同的虚函数父类必须写“virtual”子类可以不写但是不规范classAnimal{public:virtualvoidtalk()const0;// 虚函数};classDog:publicAnimal{public:// TODO: 重写 talk输出 汪汪virtualvoidtalk()const{cout汪汪endl;}};classCat:publicAnimal{public:// TODO: 重写 talk输出 (^ω^)喵virtualvoidtalk()const{cout喵喵endl;}};voidletsHear(constAnimalanimal)// 注意基类引用{// TODO: 调用 talkanimal.talk();}intmain(){Cat cat;Dog dog;// TODO: 分别传入 cat 和 dogletsHear(cat);letsHear(dog);return0;2.1 虚函数的默认参数陷阱选择题要实现什么理解一个易错点——重写虚函数时默认参数在编译期就确定了用的是「当前调用点静态类型」的默认值而不是实际被调用的派生类函数的默认值。题目以下程序输出结果是 A: A-0 B: B-1 C: A-1 D: B-0 E: 编译出错 F: 以上都不正确classA{public:virtualvoidfunc(intval1){coutA-valendl;}virtualvoidtest(){func();}};classB:publicA{public:voidfunc(intval0){coutB-valendl;}};intmain(){B*pnewB;p-test();// 问输出什么return0;}答案BB-1。逐步拆解p-test()test是A的虚函数B没重写它所以调A::test()在A::test()内部func()等价于this-func()this的静态类型是A*但真实指向B对象func是虚函数 → 动态绑定 → 实际调B::func()打印B-默认参数在编译期确定this静态类型是A*所以默认值取A::func的1不是B的0结果B-1。p-func();// 输出B-0而p-func()中p是B*静态类型是B默认值取B的0输出B-0。4.析构函数是虚函数前提B继承了AA* p2 new B;// 基类指针指向派生类对象结果子类对象B在内存中是包含了父类对象A的部分的。必须先把上面的房子子类拆掉再拆地基父类。delete p2; 调 ~B() 再 ~A()#includeiostreamusingnamespacestd;classA{public:virtual~A(){cout~A()endl;}};classB:publicA{public:~B(){cout~B()-delete:_pendl;delete_p;// 释放 B 自己申请的资源}protected:int*_pnewint[10];};intmain(){A*p1newA;A*p2newB;// 基类指针指向派生类对象deletep1;// 调 ~A()deletep2;// 调 ~B() 再 ~A()因为 ~A 是虚函数 → 多态return0;}5.协变了解即可是什么一种「返回值类型不同、但也能构成重写」的特殊情况基类虚函数返回基类对象的指针或引用派生类重写时返回派生类对象的指针或引用也构成重写。6.override 和 final 关键字override检查「到底有没有真的重写成功」final禁止派生类再重写某个虚函数。位置函数声明的最后面参数列表的括号后面函数体或分号的前面#includeiostreamusingnamespacestd;// override检查是否真的构成重写 // 下面故意把 Dirve 拼错正确是 Drive所以没有重写任何基类函数// 加了 override 编译器直接报错// error C3668: Benz::Drive: 包含重写说明符 override 的方法没有重写任何基类方法classCar{public:virtualvoidDirve(){}// 注意基类这里写成了 Dirve老师故意挖坑};classBenz:publicCar{public:virtualvoidDrive()override// 编译报错{coutBenz-舒适endl;}};// final禁止派生类重写 // error C3248: Car::Drive: 声明为 final 的函数无法被 Benz::Drive 重写classCar2{public:virtualvoidDrive()final{}};classBenz2:publicCar2{public:virtualvoidDrive()// 编译报错{coutBenz-舒适endl;}};intmain(){return0;}7.纯虚函数 和 抽象类纯虚函数写法虚函数后面加上“ 0”抽象类定义含有纯虚函数的类是抽象类子类继承的父类有纯虚函数并且子类没有重写该函数那么子类也是抽象类比喻纯虚函数父类给子类留下的一个必须完成的任务抽象类就像车这个东西如果不加上车牌号等参数那就并不完整不能上路classCar{public:virtualvoidDrive()0;// TODO: 定义纯虚函数在虚函数声明后写 0};classBenz:publicCar{public:virtualvoidDrive(){// TODO: 输出 Benz-舒适coutBenz-舒适endl;}};classBMW:publicCar{public:virtualvoidDrive(){// TODO: 输出 BMW-操控coutBMW-操控endl;}};intmain(){// Car car; // TODO 思考这行为什么编译报错// TODO: 用基类指针指向 Benz 和 BMW并调用 DriveCar*carnewBMW;car-Drive();return0;}多态的原理1.虚函数表指针/虚表指针**是什么**在含有虚函数的类创建的对象中会在开头包含一个指针这个指针指向一个函数指针数组的地址通过这个指针就能找到这个类对象中的所有虚函数有什么用实现多态——运行时先找虚表再根据虚表中的地址找到对应的虚函数个数可能有多个因为一般继承下来的基类部分里已有虚表指针派生类自己就不再单独生成一个继承多个类就会继承多个虚表1.1 规则基类对象的虚表存「基类所有虚函数」的地址派生类由两部分组成继承下来的基类部分 自己的成员。一般继承下来的基类部分里已有虚表指针派生类自己就不再单独生成一个派生类重写了基类的虚函数虚表中对应位置就被覆盖成派生类的函数地址派生类虚表 基类虚函数地址未被重写的 被覆盖的派生类函数地址 派生类自己新增的虚函数地址。1.2动态绑定 和 静态绑定满足多态条件时是「动态绑定」运行时到虚表找地址否则是「静态绑定」编译时直接确定地址。静态绑定动态绑定条件不满足多态条件如非虚函数、或对象直接调用指针/引用 虚函数时机编译时确定函数地址运行时到虚表查地址汇编特征call Student::BuyTicket直接地址mov eax,[edx]; call eax先取虚表再间接调用
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Excel一键生成柱状图:Alt+F1高效数据可视化技巧 2026/9/29 22:43:01

Excel一键生成柱状图:Alt+F1高效数据可视化技巧

先说一件我自己的事。前几年做月度经营分析,每月固定要出十几张数据对比表,领导统一要求:数字旁边必须有图。那会儿我还在用最笨的办法,点“插入”→“图表”→再在弹窗里层层选类型,一套流程走完少说一分多钟。后来偶…

阅读更多 →
AI Agent知识获取管道:RAG检索增强生成全流程与TypeScript实战 2026/9/29 22:43:01

AI Agent知识获取管道:RAG检索增强生成全流程与TypeScript实战

1. 为什么知识获取管道是 AI Agent 的分水岭做 AI Agent 的人迟早会撞上一堵墙:模型本身很聪明,但你问它公司内部的报销流程、上周刚更新的接口文档、某个客户的特殊约定,它要么一本正经地胡说,要么干脆承认不知道。这不是模型不行…

阅读更多 →
告别调参侠:用NumPy和Pandas筑牢AI数据管线 2026/9/29 22:42:48

告别调参侠:用NumPy和Pandas筑牢AI数据管线

1. 项目概述:为什么“调参侠”注定走不远大概每个玩过深度学习的朋友,都经历过那种白天黑夜盯着loss曲线、疯狂改学习率、换优化器、调batch size的日子。我自己就曾连续两周窝在实验室里,一遍遍跑同一个模型,就为了把验证集准确率…

阅读更多 →
I2C总线鲁棒性设计:时钟延展与死锁恢复硬核实践 2026/9/29 22:42:35

I2C总线鲁棒性设计:时钟延展与死锁恢复硬核实践

1. 这不是教科书里的“设计模式”,而是芯片级通信系统里活生生的生死线 你手头那块刚焊好的开发板,I2C总线上挂了温湿度传感器、EEPROM、OLED屏、触摸IC——四五个从设备排成一串,时钟线SCL和数据线SDA像一根绷紧的琴弦。某天深夜调试&#x…

阅读更多 →
汉服热背后的古诗词消费:谁在穿,谁在读,谁在买单? 2026/9/29 22:42:35

汉服热背后的古诗词消费:谁在穿,谁在读,谁在买单?

2025年3月,杭州西湖边的一场花朝节活动上,数百名汉服爱好者列队巡游。队伍中,一个穿明制袄裙的女孩举着手机直播,镜头扫过她身后的人群时,弹幕里跳出一句:“你们穿的这是汉服,那你们读过《诗经》…

阅读更多 →
AtlasX社区版开源:小白也能轻松入门网络安全资产梳理与风险挖掘(收藏必备) 2026/9/29 22:42:34

AtlasX社区版开源:小白也能轻松入门网络安全资产梳理与风险挖掘(收藏必备)

AtlasX社区版开源:小白也能轻松入门网络安全资产梳理与风险挖掘(收藏必备) 阿特拉斯X(AtlasX)社区版开源,旨在帮助企业快速侦察和梳理外网资产,构建暴露面资产信息库。系统通过多源数据采集、资…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉