12.16 C++中的多態(動態多態)究竟是如何實現

為了敘述簡便,在本文中,將動態多態性一律簡化為多態性。

在前面的文章中,我們已經簡要介紹了C++的多態性,也介紹了C++的虛函數表,下面,我們來看看C++是如何利用虛函數機制來實現多態性的。(題外話:實現多態性並不一定需要用到虛函數機制)。下面,我們還是從程序的角度來看,為了便於熱身,我們來看一個極為簡單的程序:

#include <iostream>

using namespace std;


class E

{

public:


virtual void f()

{

cout << "E::f" << endl;

};


virtual void g()

{

cout << "E::g" << endl;

};

};


class M : public E

{

public:

virtual void g()

{

cout << "M::g" << endl;

};

};


int main()

{

E e;

M m;


E *p = &e;

p->f(); // E::f

p->g(); // E::g


p = &m;

p->f(); // E::f

p->g(); // M::g


return 0;

}

為什麼同樣是調用p->g();這個語句,得到了截然不同的結果呢?因為多態嘛!那這種多態性是如何實現的呢?廢話不多說,直接上代碼:

#include <iostream>

using namespace std;


class E

{

public:


// 為了方便敘述,故把公開a和b, 在實際系統中,很少這樣做

int a;

int b;


virtual void f()

{

cout << "E::f" << endl;

};


virtual void g()

{

cout << "E::g" << endl;

};

};


class M : public E

{

public:


int c;

virtual void g()

{

cout << "M::g" << endl;

};

};


int main()

{

E e;

e.a = 1;

e.b = 2;

cout << &e << endl; // e的VTABLE的地址: 0012FF74

cout << (int *)&e << endl; // eVPTR的地址: 0012FF74

cout << &e.a << endl; // e.a的地址: 0012FF78

cout << &e.b << endl; // e.b的地址: 0012FF7C


cout << (void *)*((int *)&e) << endl; // eVPTR的值 0046F028

cout << *((int *)&e + 1) << endl; // e.a的值: 1

cout << *((int *)&e + 2) << endl; // e.b的值: 2


cout << (void *)*(int *)(*(int *)&e) << endl; // E的f函數的地址: 0040128F

cout << (void *)*((int *)(*(int *)&e) + 1) << endl; // E的g函數的地址: 004011BD


cout << "---------" << endl;


M m;

m.a = 3;

m.b = 4;

m.c = 5;

cout << &m << endl; // m的VTABLE的地址: 0012FF64

cout << (int *)&m << endl; // mVPTR的地址: 0012FF64

cout << &m.a << endl; // m.a的地址: 0012FF68

cout << &m.b << endl; // m.b的地址: 0012FF6C

cout << &m.c << endl; // m.c的地址: 0012FF70


cout << (void *)*((int *)&m) << endl; // mVPTR的值 0046F034

cout << *((int *)&m + 1) << endl; // m.a的值: 3

cout << *((int *)&m + 2) << endl; // m.b的值: 4

cout << *((int *)&m + 3) << endl; // m.c的值: 5


cout << (void *)*(int *)(*(int *)&m) << endl; // E的f函數的地址: 0040128F

cout << (void *)*((int *)(*(int *)&m) + 1) << endl; // M的g函數的地址: 004011A8


E *p = &e;

p->f(); // E::f

p->g(); // E::g


E *q = &m;

q->f(); // E::f

q->g(); // M::g


return 0;

}

為了理解上面的程序和結果,我來畫一幅圖,大家就能大致明白,圖如下:

C++中的多態(動態多態)究竟是如何實現

為了配合理解上圖,下面隨即給出調試程序的結果圖:

C++中的多態(動態多態)究竟是如何實現

C++中的多態(動態多態)究竟是如何實現

現在應該清楚了用虛函數實現多態性的原理了吧!OK,最後感嘆一句:Everything should be made as simple as possible.

最後,如果你想學C/C++可以私信小編“01”獲取素材資料以及開發工具和聽課權限哦!


分享到:


相關文章: