C++?多態(tài)虛函數(shù)的底層原理深入理解
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)物在說(shuō)話" << endl;
}
virtual void eat(int a )
{
cout << "動(dòng)物在吃飯" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "小貓?jiān)谡f(shuō)話" << endl;
}
void eat(int a)
{
cout << "小貓?jiān)诔燥? << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "小狗在說(shuō)話" << endl;
}
};這兩個(gè)類實(shí)現(xiàn)集成關(guān)系,簡(jiǎn)單來(lái)說(shuō)就是 Animal是父類,Cat是子類,通過(guò)父類引用調(diào)用子類函數(shù),這就是多態(tài)(字面意思就是一個(gè)對(duì)象多個(gè)狀態(tài)),這樣就 符合** 高內(nèi)聚低耦合** 的設(shè)計(jì)原則,更容易 后期維護(hù)與修改
1.2 怎么實(shí)現(xiàn)多態(tài)
說(shuō)了這么多,那么多態(tài)到底怎么實(shí)現(xiàn)呢?
- 想必上面代碼中也已經(jīng)透露出了一些信息,并且十分關(guān)鍵。沒(méi)錯(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è)條件:
- 注:如果沒(méi)有多態(tài),那么父類指向子類時(shí)就無(wú)法調(diào)用子類函數(shù),也就是此時(shí)該函數(shù)地址早就綁定好了,只能是animal說(shuō)話,屬于靜態(tài)聯(lián)編(靜態(tài));如果想調(diào)用小貓說(shuō)話,這個(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)用貓說(shuō)話,因?yàn)镃/C++默認(rèn)調(diào)用慣例 __cdecl,而用下列調(diào)用時(shí) 是__stdcall
typedef void( __stdcall *FUNPOINT)(int); (FUNPOINT (*((int*)*(int*)animal + 1)))(10);


到此這篇關(guān)于C++ 多態(tài)虛函數(shù)的底層原理深入理解的文章就介紹到這了,更多相關(guān)C++ 多態(tài)虛函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++文件關(guān)鍵詞快速定位出現(xiàn)的行號(hào)實(shí)現(xiàn)高效搜索
這篇文章主要為大家介紹了C++文件關(guān)鍵詞快速定位出現(xiàn)的行號(hào)實(shí)現(xiàn)高效搜索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
解析sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應(yīng)用
本篇文章是對(duì)sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Qt音視頻開(kāi)發(fā)之音頻播放QAudioOutput的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)音頻播放QAudioOutput功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt開(kāi)發(fā)有一定的幫助,需要的可以參考一下2023-03-03
C++實(shí)現(xiàn)轉(zhuǎn)置矩陣的循環(huán)
大家好,本篇文章主要講的是C++實(shí)現(xiàn)轉(zhuǎn)置矩陣的循環(huán),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01

