網(wǎng)站首頁 編程語言 正文
1?多態(tài)的基本概念
1.1 什么是多態(tài)?
- 多態(tài)是在不同繼承關(guān)系的類對(duì)象,去調(diào)用同一函數(shù),產(chǎn)生了不同的行為,通常是父類調(diào)用子類的重寫函數(shù),在C++中就是 父類指針指向子類對(duì)象,此時(shí)父類指針的向下引用就可以實(shí)現(xiàn)多態(tài)
比如看下面的代碼:
class Animal { public: //虛函數(shù) virtual void speak() { cout << "動(dòng)物在說話" << endl; } virtual void eat(int a ) { cout << "動(dòng)物在吃飯" << endl; } }; class Cat :public Animal { public: void speak() { cout << "小貓?jiān)谡f話" << endl; } void eat(int a) { cout << "小貓?jiān)诔燥? << endl; } }; class Dog :public Animal { public: void speak() { cout << "小狗在說話" << endl; } };
這兩個(gè)類實(shí)現(xiàn)集成關(guān)系,簡單來說就是 Animal是父類,Cat是子類,通過父類引用調(diào)用子類函數(shù),這就是多態(tài)(字面意思就是一個(gè)對(duì)象多個(gè)狀態(tài)),這樣就 符合** 高內(nèi)聚低耦合** 的設(shè)計(jì)原則,更容易 后期維護(hù)與修改
1.2 怎么實(shí)現(xiàn)多態(tài)
說了這么多,那么多態(tài)到底怎么實(shí)現(xiàn)呢?
- 想必上面代碼中也已經(jīng)透露出了一些信息,并且十分關(guān)鍵。沒錯(cuò),就是virtual,字面意思是 虛擬的,而也的確如此,這個(gè)關(guān)鍵字修飾的 函數(shù),叫做虛函數(shù),擁有虛函數(shù)的 類,被稱為?抽象類(虛類),virtual是實(shí)現(xiàn)多態(tài)的必要不充分條件
- 同時(shí) ,子類要重寫父類的虛函數(shù),什么叫重寫?就是函數(shù)類型,函數(shù)名,參數(shù)列表完全相同。
- 并且父類指針還要指向子類對(duì)象,
正如下所示:
void doSpeak(Animal & animal) //Animal & animal = cat; { animal.speak(); } void test01() { Cat cat; doSpeak(cat); Dog dog; doSpeak(dog); }
如此方能滿足實(shí)現(xiàn)多態(tài)的三個(gè)條件:
- 注:如果沒有多態(tài),那么父類指向子類時(shí)就無法調(diào)用子類函數(shù),也就是此時(shí)該函數(shù)地址早就綁定好了,只能是animal說話,屬于靜態(tài)聯(lián)編(靜態(tài));如果想調(diào)用小貓說話,這個(gè)時(shí)候函數(shù)的地址就不能早就綁定好,而是在運(yùn)行階段再去綁定函數(shù)地址,屬于地址晚綁定,叫動(dòng)態(tài)聯(lián)編,(動(dòng)態(tài))多態(tài)的實(shí)現(xiàn)就是依靠動(dòng)態(tài)聯(lián)編。
2 虛函數(shù)的底層原理
那么虛函數(shù)到底是怎么工作的呢?
void test02() { Animal * animal = new Cat; ((void(*)()) (*(int *)*(int *)animal)) (); typedef void( __stdcall *FUNPOINT)(int); (FUNPOINT (*((int*)*(int*)animal + 1)))(10); }
Animal * animal = new Cat;
就是animal->speak();
((void(*)()) (*(int *)*(int *)animal)) ();
這里?*(int *)animal
?解引用到虛函數(shù)表中,先將animal類型的指針強(qiáng)轉(zhuǎn)為int *
,然后解引用得到int類型的值放到虛函數(shù)表中,然后偏移相應(yīng)位置指向speak()
((void(*)()) (*(int *)*(int *)animal)) ();
調(diào)用貓說話,因?yàn)镃/C++默認(rèn)調(diào)用慣例?__cdecl
,而用下列調(diào)用時(shí) 是__stdcall
typedef void( __stdcall *FUNPOINT)(int); (FUNPOINT (*((int*)*(int*)animal + 1)))(10);
原文鏈接:https://juejin.cn/post/7127677550599340046
相關(guān)推薦
- 2023-03-19 教你如何實(shí)現(xiàn)在react項(xiàng)目中嵌入Blazor_React
- 2022-07-06 c#?模擬串口通信?SerialPort的實(shí)現(xiàn)示例_C#教程
- 2022-09-26 python中創(chuàng)建一個(gè)包并引用使用的操作方法_python
- 2023-02-27 c++數(shù)組排序的5種方法實(shí)例代碼_C 語言
- 2022-12-23 Kotlin?select使用方法介紹_Android
- 2022-09-27 Golang?Mutex互斥鎖深入理解_Golang
- 2023-07-25 node項(xiàng)目使用crypto模塊為用戶密碼加密
- 2022-12-12 pycharm?console?打印中文為亂碼問題及解決_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支