網站首頁 編程語言 正文
1?多態的基本概念
1.1 什么是多態?
- 多態是在不同繼承關系的類對象,去調用同一函數,產生了不同的行為,通常是父類調用子類的重寫函數,在C++中就是 父類指針指向子類對象,此時父類指針的向下引用就可以實現多態
比如看下面的代碼:
class Animal { public: //虛函數 virtual void speak() { cout << "動物在說話" << endl; } virtual void eat(int a ) { cout << "動物在吃飯" << endl; } }; class Cat :public Animal { public: void speak() { cout << "小貓在說話" << endl; } void eat(int a) { cout << "小貓在吃飯" << endl; } }; class Dog :public Animal { public: void speak() { cout << "小狗在說話" << endl; } };
這兩個類實現集成關系,簡單來說就是 Animal是父類,Cat是子類,通過父類引用調用子類函數,這就是多態(字面意思就是一個對象多個狀態),這樣就 符合** 高內聚低耦合** 的設計原則,更容易 后期維護與修改
1.2 怎么實現多態
說了這么多,那么多態到底怎么實現呢?
- 想必上面代碼中也已經透露出了一些信息,并且十分關鍵。沒錯,就是virtual,字面意思是 虛擬的,而也的確如此,這個關鍵字修飾的 函數,叫做虛函數,擁有虛函數的 類,被稱為?抽象類(虛類),virtual是實現多態的必要不充分條件
- 同時 ,子類要重寫父類的虛函數,什么叫重寫?就是函數類型,函數名,參數列表完全相同。
- 并且父類指針還要指向子類對象,
正如下所示:
void doSpeak(Animal & animal) //Animal & animal = cat; { animal.speak(); } void test01() { Cat cat; doSpeak(cat); Dog dog; doSpeak(dog); }
如此方能滿足實現多態的三個條件:
- 注:如果沒有多態,那么父類指向子類時就無法調用子類函數,也就是此時該函數地址早就綁定好了,只能是animal說話,屬于靜態聯編(靜態);如果想調用小貓說話,這個時候函數的地址就不能早就綁定好,而是在運行階段再去綁定函數地址,屬于地址晚綁定,叫動態聯編,(動態)多態的實現就是依靠動態聯編。
2 虛函數的底層原理
那么虛函數到底是怎么工作的呢?
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
?解引用到虛函數表中,先將animal類型的指針強轉為int *
,然后解引用得到int類型的值放到虛函數表中,然后偏移相應位置指向speak()
((void(*)()) (*(int *)*(int *)animal)) ();
調用貓說話,因為C/C++默認調用慣例?__cdecl
,而用下列調用時 是__stdcall
typedef void( __stdcall *FUNPOINT)(int); (FUNPOINT (*((int*)*(int*)animal + 1)))(10);
原文鏈接:https://juejin.cn/post/7127677550599340046
相關推薦
- 2022-12-29 Android動態加載布局實現技巧介紹_Android
- 2022-01-26 iconv(): Detected an illegal character in input st
- 2022-05-08 jquery實現淘寶詳情頁選擇套餐_jquery
- 2022-02-27 解決No converter for XXX with preset Content-Type ‘a
- 2023-03-04 c++元編程模板函數重載匹配規則示例詳解_C 語言
- 2022-02-17 docker容器內的數據存放在哪里
- 2022-12-31 Android權限機制深入分析講解_Android
- 2022-10-10 C++淺析程序中內存的分布_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支