面向对象编程(OOP)的三大特性之一(封装、继承、多态)就是第八章聚焦于C++的多态(Polymorphism),这
本章聚焦于C++的多态(Polymorphism),这是面向对象编程(OOP)的三大特性之一(封装、继承、多态),与之前的章节(第一章:C++基础、第二章:类和对象(上)、第三章:类和对象(下)、第四章:内存管理、第五章:模板、第六章:STL、第七章:继承、第十五章:哈希表)紧密相关。多态为实现灵活、可扩展的代码提供了支持,尤其在设计复杂数据结构(如哈希表)时非常有用。简要概述每个部分的内容,提供简洁的C++代码示例,并保持与之前学习的章节衔接。
前言
多态允许同一接口在不同对象上表现出不同行为,是C++面向对象编程的核心特性。本章介绍多态的实现、虚函数、抽象类、虚函数表等内容,为实现动态行为和设计模式奠定基础,同时与哈希表等数据结构的扩展性设计相关。
1. 多态的概念
- 多态:同一操作作用于不同对象,产生不同行为。
- 分类:
- 编译期多态:通过函数重载、模板(第五章)实现。
- 运行期多态:通过继承和虚函数实现,动态绑定行为。
- 应用:多态提高代码扩展性和复用性,常见于框架设计和接口实现。
2. 多态的实现
运行期多态通过继承(第七章)和虚函数实现:
- 基类定义虚函数,派生类重写(override)以提供特定实现。
- 通过基类指针或引用调用虚函数,动态绑定到实际对象类型。
代码示例:
#include <iostream>class Base {public:virtual void print() { std::cout << "Base" << std::endl; } // 虚函数};class Derived : public Base {public:void print() override { std::cout << "Derived" << std::endl; } // 重写};int main() {Base* b = new Derived(); // 基类指针指向派生类b->print(); // 输出:Derived(动态绑定)delete b;return 0;}
3. 虚函数的重写
3.1 重写
- 派生类重写基类的虚函数,函数签名(名称、参数、返回值)必须一致。
- 需在基类中用
virtual
关键字标记虚函数。
代码示例:
#include <iostream>class Base {public:virtual void func() { std::cout << "Base func" << std::endl; }};class Derived : public Base {public:void func() override { std::cout << "Derived func" << std::endl; }};int main() {Base* b = new Derived();b->func(); // 输出:Derived funcdelete b;return 0;}
3.2 协变
协变允许派生类重写虚函数时,返回类型是基类返回类型的派生类(通常用于指针或引用)。
代码示例:
#include <iostream>class Base {public:virtual Base* clone() { return new Base(); }};class Derived : public Base {public:Derived* clone() override { return new Derived(); } // 协变返回类型};int main() {Base* b = new Derived();Base* c = b->clone(); // 返回Derived*,但安全转换为Base*delete b;delete c;return 0;}
3.3 析构函数的重写
- 基类析构函数应声明为
virtual
,否则通过基类指针删除派生类对象时,只调用基类析构函数,可能导致资源泄漏。 - 派生类析构函数自动重写基类的虚析构函数。
代码示例:
#include <iostream>class Base {public:virtual ~Base() { std::cout << "Base destructor" << std::endl; }};class Derived : public Base {public:~Derived() override { std::cout << "Derived destructor" << std::endl; }};int main() {Base* b = new Derived();delete b; // 输出:Derived destructor, Base destructorreturn 0;}
3.4 override和final关键字
override
(C++11):显式声明函数重写基类虚函数,确保签名匹配。final
(C++11):禁止派生类进一步重写虚函数或继承类。
代码示例:
#include <iostream>class Base {public:virtual void func() { std::cout << "Base func" << std::endl; }};class Derived : public Base {public:void func() override final { std::cout << "Derived func" << std::endl; } // final禁止重写};class SubDerived : public Derived {// void func() override; // 错误:func是final};int main() {Base* b = new Derived();b->func(); // 输出:Derived funcdelete b;return 0;}
3.5 重载、重写和隐藏的对比(重点)
特性 | 重载(Overload) | 重写(Override) | 隐藏(Hiding) |
---|---|---|---|
定义 | 同作用域,函数名相同,参数不同 | 继承关系,虚函数签名一致 | 派生类同名函数隐藏基类函数 |
关键字 | 无 | virtual /override | 无 |
作用域 | 同一类或命名空间 | 基类与派生类 | 基类与派生类 |
绑定 | 编译期 | 运行期(动态绑定) | 编译期 |
代码示例:
#include <iostream>class Base {public:virtual void func() { std::cout << "Base func" << std::endl; } // 虚函数void func(int x) { std::cout << "Base func with int: " << x << std::endl; } // 重载};class Derived : public Base {public:void func() override { std::cout << "Derived func" << std::endl; } // 重写void func(double x) { std::cout << "Derived func with double: " << x << std::endl; } // 隐藏};int main() {Base* b = new Derived();b->func(); // 输出:Derived func(重写)// b->func(3.14); // 错误:Base无func(double)Derived d;d.func(3.14); // 输出:Derived func with double: 3.14(隐藏)d.Base::func(5); // 输出:Base func with int: 5(访问隐藏的基类函数)delete b;return 0;}
5. 纯虚函数和抽象类
- 纯虚函数:声明为
virtual void func() = 0;
,无实现,派生类必须重写。 - 抽象类:包含至少一个纯虚函数的类,不能实例化,常用作接口。
代码示例:
#include <iostream>class Shape {public:virtual void draw() = 0; // 纯虚函数virtual ~Shape() = default; // 虚析构函数};class Circle : public Shape {public:void draw() override { std::cout << "Draw Circle" << std::endl; }};int main() {// Shape s; // 错误:抽象类不可实例化Shape* s = new Circle();s->draw(); // 输出:Draw Circledelete s;return 0;}
6. 多态的原理
- 运行期多态通过**虚函数表(vtable)**实现。
- 基类指针或引用调用虚函数时,根据对象实际类型的vtable查找函数地址。
- 虚函数调用有少量运行时开销,但提供动态行为。
7. 虚函数表
- 虚函数表(vtable):每个包含虚函数的类有一个vtable,存储虚函数地址。
- 对象布局:对象包含一个虚表指针(vptr),指向类的vtable。
- 动态绑定:通过vptr查找vtable中的函数地址。
代码示例(示意vtable行为):
#include <iostream>class Base {public:virtual void func1() { std::cout << "Base func1" << std::endl; }virtual void func2() { std::cout << "Base func2" << std::endl; }};class Derived : public Base {public:void func1() override { std::cout << "Derived func1" << std::endl; }};int main() {Base* b = new Derived();b->func1(); // 输出:Derived func1(通过vtable调用)b->func2(); // 输出:Base func2delete b;return 0;}
8. 动态绑定与静态绑定
- 动态绑定:运行期通过vtable确定虚函数调用,适用于多态。
- 静态绑定:编译期确定函数调用,适用于非虚函数或直接调用。
- 区别:
- 动态绑定:基类指针/引用调用虚函数,运行时解析。
- 静态绑定:函数调用在编译时确定,效率更高。
代码示例:
#include <iostream>class Base {public:virtual void dynamicFunc() { std::cout << "Base dynamic" << std::endl; }void staticFunc() { std::cout << "Base static" << std::endl; }};class Derived : public Base {public:void dynamicFunc() override { std::cout << "Derived dynamic" << std::endl; }void staticFunc() { std::cout << "Derived static" << std::endl; }};int main() {Base* b = new Derived();b->dynamicFunc(); // 输出:Derived dynamic(动态绑定)b->staticFunc(); // 输出:Base static(静态绑定)delete b;return 0;}
尾声
多态通过虚函数和动态绑定实现了灵活的行为切换,是C++面向对象编程的核心。本章内容为实现复杂数据结构(如哈希表)提供了扩展性支持,同时为后续学习设计模式和高级OOP技术奠定了基础。
补充说明
- 与哈希表章节的衔接:多态可用于哈希表的扩展设计。例如,定义一个抽象基类
HashTableBase
(含纯虚函数),派生出不同的哈希表实现(如链地址法、开放寻址法)。
示例多态哈希表(结合第八章和第十五章):#include <iostream>#include <list>template<typename K, typename V>class HashTableBase {public:virtual void insert(K key, V value) = 0;virtual V find(K key) const = 0;virtual ~HashTableBase() = default;};template<typename K, typename V>class ChainingHashTable : public HashTableBase<K, V> {private:static const int SIZE = 10;std::list<std::pair<K, V>> table[SIZE];public:void insert(K key, V value) override {table[std::hash<K>{}(key) % SIZE].push_back({key, value});}V find(K key) const override {for (const auto& pair : table[std::hash<K>{}(key) % SIZE]) {if (pair.first == key) return pair.second;}return V();}};int main() {HashTableBase<int, std::string>* ht = new ChainingHashTable<int, std::string>();ht->insert(1, "Alice");std::cout << ht->find(1) << std::endl; // 输出:Alicedelete ht;return 0;}
- 进一步需求:
- 如果你需要更详细的代码实现(如虚函数表的可视化、不同哈希表实现的比较)、图表(例如vtable结构图)、或某一节的深入讲解(如动态绑定的底层机制),请告诉我。
- 如果你有其他章节的内容需要讲解,或想结合第一章至第七章、第十五章的内容,请具体说明!
希望这部分解答对你学习C++多态有帮助! 如果有任何问题,随时告诉我!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927094.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
ai提交消息常用的 chore,原来是个单词(琐事/零散任务)+约定,用于非功能性提交
在使用 AI 辅助生成 Git 提交消息时,你经常会看到以 chore: 开头的提交信息,比如:
chore: update dependencies
chore: clean up unused files
chore: reformat code with prettier那么,chore 到底是什么意思?✅ …
答疑解惑:无人机是否一定有主控,主控和飞控是一个东西吗,无人机是否只有飞控就可以飞行???
答疑解惑:无人机是否一定有主控,主控和飞控是一个东西吗,无人机是否只有飞控就可以飞行???相关:
https://item.taobao.com/item.htm?ali_refid=a3_430582_1006%3A1123627528%3AN%3ACpoHEyrZTY3ym41xzFawEg%3D%…
健身器材网站源码广东品牌设计公司有哪些
网址如下:
P2246 SAC#1 - Hello World(升级版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 刚开始是用递归做的,虽然用了哈希表优化,但是超时,只得了50
后面想到了一个新的算法,时间复杂度…
网站更换服务器对seo的影响吉安seo
前文
Flutter 是一个跨平台的开发框架,它允许开发者使用相同的代码库来构建 iOS、Android、Web 和桌面应用程序。
上文flutter开发多端平台应用的探索 上(基本操作)-CSDN博客列举了一些特定平台的case(桌面端菜单,鼠…
博物馆网站模版海外广告公司
元素: 用法: 标签名:{style的内容} 特点: 全局性,使用后,所有的相同标签都是同一种样式。 举例: <!DOCTYPE html>
<html lang"en"><head><meta charset"UT…
The Brain in Your Toes: Can Tiny Foot Movements Boost BDNF and Sharpen the Mind? - 教程
The Brain in Your Toes: Can Tiny Foot Movements Boost BDNF and Sharpen the Mind? - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !imp…
一直好奇无人机飞控上的SD卡槽是不是用来装系统盘的,结果发现这个其实就是个数据存储的作用,飞控板子上自带系统盘存储芯片
一直好奇无人机飞控上的SD卡槽是不是用来装系统盘的,结果发现这个其实就是个数据存储的作用,飞控板子上自带系统盘存储芯片飞控烧录器:
https://item.taobao.com/item.htm?abbucket=17&id=740054798017&mi…
做网站宁夏网站建设必备的功能模块
目录
一、为什么 JavaScript 是单线程?
二、JavaScript是单线程,怎样执行异步的代码?
三、事件循环机制
四、代码1
五、结果1
六、代码2
七、结果2 一、为什么 JavaScript 是单线程?
JavaScript 语言的一大特点就是单线程…
四旋翼无人机 —— 飞控硬件推荐 —— 微空MicoAir743 V2飞控双IMU蓝牙调参 支持APM/PX4/INAV/BF固件
四旋翼无人机 —— 飞控硬件推荐 —— 微空MicoAir743 V2飞控双IMU蓝牙调参 支持APM/PX4/INAV/BF固件地址:
https://item.taobao.com/item.htm?abbucket=17&id=865586536210&mi_id=0000AtX69t4F6w_welOrXNQ…
详细介绍:OpenAI近日推出了一项名为 ChatGPT Pulse 的全新功能
详细介绍:OpenAI近日推出了一项名为 ChatGPT Pulse 的全新功能2025-10-04 11:26
tlnshuju
阅读(0)
评论(0) 收藏
举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impo…
详细介绍:Kafka09-速答-尚硅谷
详细介绍:Kafka09-速答-尚硅谷pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&quo…
GPT‑5 都更新了些什么? - 实践
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
网站解析后显示建设中wordpress 开放适配
同个人博客:http://tsundere-x.top/
一、互斥
为何需要引入互斥机制?
当多个线程对同一数据并发读写(至少有一个线程执行写操作)时,这种情形被称为竞争。竞争会导致数据读或写的不确定性。而有时这种不确定性是不可…
哈尔滨公司建站模板网站建设与网页设计试卷
本文要介绍的是ASP.NET怎样读写文本文件,但更重要的是实现的过程。使用的工具是Visual Studio 2015 ,.NET版本是4.6.1 。一共建立的2个项目,HoverTreePanel和HoverTreeWeb,都是ASP.NET项目。文章末尾附源码下载。项目结果如下图&a…
导购类网站怎么做网站建设推荐书籍
PointNet 是一种深度网络架构,它使用点云来实现从对象分类、零件分割到场景语义解析等应用。 它于 2017 年实现,是第一个直接将点云作为 3D 识别任务输入的架构。
本文的想法是使用 Pytorch 实现 PointNet 的分类模型,并可视化其转换以了解模…
day15 课程(继承 )
day15 课程(继承 & )课程:https://www.bilibili.com/video/BV1o4411M71o?spm_id_from=333.788.videopod.episodes&p=292
15.1 了解继承------------------------------------------------ 执行后15.2 扩展…
前端安全障碍深度解析:从原理到实践的全方位防护指南
pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …
node菜单服务引起的后台异常表象到运维释放从库的数据库连接及驱动修改配置,重新部署生效
node菜单服务引起的后台异常表象到运维释放从库的数据库连接及驱动修改配置,重新部署生效node菜单服务引起的后台异常表象到运维释放从库的数据库连接及驱动修改配置,重新部署生效
1.刚开始判断是node服务挂了,jenk…
制作网站难还是编程难简约网站后台
目录 linux用户相关linux挂载网络共享文件wsl相关docker相关配置打包镜像导出镜像导入镜像window清理wsl和docker空间window查看网络中计算机的ipv4linux用户相关 添加新用户sudo adduser --home /home/<用户名> <用户名>查看权限id <用户名>添加权限sudo us…