C++多态的基本语法与原理剖析
多態分為兩類
1.靜態多態:函數重載和運算符重載屬于靜態多態,復用函數名
2.動態多態:派生類和虛函數實現運行時多態
靜態多態和動態多態區別:
1.靜態多態的函數地址早綁定,編譯階段確定函數地址
2.多態多態的函數地址晚綁定,運行階段確定函數地址
首先讓我們看這段代碼:
#include <iostream> using namespace std;class Animal {public:void speak() {cout << "動物在說話" << endl;} };class Cat : public Animal {public:void speak() {cout << "小貓在說話" << endl;} };void dospeak(Animal &animal) {animal.speak();}void test01() {Cat cat;dospeak(cat);}int main() {test01();system("pause");return 0; }結果為:動物在說話
我們想要的是貓在說話,可最后輸出的結果卻是動物在說話,為什么呢?
因為dospeak函數地址早綁定了,在編譯階段就確定了函數地址
那么我們要怎樣做才能讓貓說話呢?
非常簡單,就是利用動態多態,就是要讓dospeak函數的地址晚綁定(在運行階段進行綁定),我們只要在父類的同名speak函數前面加virtual關鍵字,現在speak函數就變成了虛函數,就解決了上述問題。
代碼如下:
#include <iostream> using namespace std;class Animal {public:virtual void speak() {cout << "動物在說話" << endl;} };class Cat : public Animal {public:void speak() {cout << "小貓在說話" << endl;} };void dospeak(Animal &animal) {animal.speak();}void test01() {Cat cat;dospeak(cat);}int main() {test01();system("pause");return 0; }結果為:貓在說話
重寫的概念:
1.函數的返回類型相同
2.函數名相同
3.參數列表相同
動態多態的滿足條件:
1.有繼承關系
2.子類要重寫父類的虛函數
動態多態的使用:
父類的指針或引用指向子類的對象
現在我們來看看多態的原理,首先我們看一下下面這段代碼:
#include <iostream> using namespace std;class Animal {public:void speak() {cout << "動物在說話" << endl;} };class Cat : public Animal {public:void speak() {cout << "小貓在說話" << endl;} };void dospeak(Animal &animal) {animal.speak();}void test01() {cout << "size of Animal = " << sizeof(Animal) << endl;}int main() {test01();system("pause");return 0; }結果為size of Animal = 1
現在我們在Animal的speak函數前面加上virtual,寫成多態的形式,結果又是多少呢?
#include <iostream> using namespace std;class Animal {public:virtual void speak() {cout << "動物在說話" << endl;} };class Cat : public Animal {public:void speak() {cout << "小貓在說話" << endl;} };void dospeak(Animal &animal) {animal.speak();}void test01() {cout << "size of Animal = " << sizeof(Animal) << endl;}int main() {test01();system("pause");return 0; }結果為:size of Animal = 4
這說明,加了virtual后,這個類的內部結構發生了改變。
那到底多了什么東西,導致這個類變成了4個字節呢?
結果:
多了指針。
現在讓我們看看這其中發生的變化,
首先我們要知道:
vfptr - 虛函數(表)指針
v - virtual
f - function
ptr - pointer
vftable - 虛函數表
v - virtual
f - function
table - table
現在讓我們看看Animal類內部結構:
Cat內部結構:
當子類重寫父類的虛函數時,子類中的虛函數表內部會替換成子類的虛函數地址
也就是說,當我們往父類Animal的speak函數前面加上virtual時,Cat的內部結構就會變成這樣:
當父類中的指針或者引用指向子類對象的時候,就發生了多態。
我們就相當于寫了這樣一段代碼:
Animal &animal = cat;
animal,speak();
當我們調用animal的speak函數時,由于指向的是Cat對象,所以編譯器會從Cat的虛函數表中找speak函數,就相當于在運行階段發生了多態。
原理:
由于我們寫了一個虛函數,類的內部發生了結構的改變,多了一個虛函數表指針,指向虛函數表,虛函數表內部寫的是虛函數的函數入口地址,當子類重寫了虛函數表,會把自身的虛函數表給替換掉,這里的替換就是Cat類中發生的替換。
總結
以上是生活随笔為你收集整理的C++多态的基本语法与原理剖析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 董明珠:格力花 1 亿开发矿井空调非常有
- 下一篇: 路特斯首款纯电轿车 Emeya 开启预订