如何用C來模擬實現多態?
要實現多態,首先咱們應充分了解多態的原理。
C++是如何實現多態的?函數
在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。若是對象類型是派生類,就調用派生類的函數;若是對象類型是基類,就調用基類的函數。佈局
也就是說:
若是類中包含了虛函數–>類對象大小+4個字節–>地址(虛表)–>虛函數集合(虛函數表)
基類虛表:按照基類虛函數的聲明次序將其添加到基類的虛表中
派生類:
一、將基類虛表中內存拷貝一份
二、若是派生類重寫基類中某個虛函數,用派生類本身的虛函數替換虛表中相同偏移量位置的基類虛函數
三、將派生類本身的虛函數添加在虛表的最後測試
多態調用原理(條件知足):
一、確認是否爲虛函數–>否(call)
二、從對象的前四個字節取虛表地址–>虛函數地址
三、傳參
四、調用this
咱們能夠用結構體和函數指針實現,以下:.net
// 幾個基本的函數,對應抽象類中的虛函數
void foo1()
{
printf("base foo1 \r\n");
}指針
void foo2(int i)
{對象
}blog
void foo3(int i, int j)
{內存
}it
// 虛表,包含了虛函數的指針
typedef struct Vtbl
{
void(*pf1)();
void(*pf2)(int);
void(*pf3)(int, int);
}Vtbl;
// 類的虛表
Vtbl g_vtbl = { &foo1, &foo2, &foo3, };
// 基類,開始處是虛表指針,後面是結構成員。
typedef struct Base
{
//Vtbl *pvtbl;
void *pvtbl;
int field1;
int field2;
}Base;
// 構造函數
// 也是一個普通的成員函數,須要一個this指針
void InitBase(Base *p)
{
p->pvtbl = &g_vtbl;
p->field1 = 0x1234;
p->field2 = 0x5678;
}
// 子類中的虛函數,重載了父類中的同類型函數
void Sfoo1()
{
// 能夠考慮調用父類中的函數
// foo1();
printf("derive foo1 \r\n");
}
void Sfoo4(char *s)
{
printf("hello %s\r\n", s);
}
// 子類中的虛表,由於內存佈局是同樣的
// 直接使用父類的
typedef struct SVtbl
{
Vtbl vtbl;
void(*pf4)(char *);
}SVtbl;
// 子類的虛表
SVtbl g_svtbl = { { &Sfoo1, &foo2, &foo3, }, &Sfoo4, };
// 某個子類,包含父類的內容
// 還有本身的成員
typedef struct Derive
{
Base a;
int field3;
}Derive;
// 構造函數
// 也是一個普通的成員函數,須要一個this指針
void InitDerive(Derive *p)
{
InitBase((Base*)p);
p->a.pvtbl = &g_svtbl;
p->field3 = 0xabcd;
}
void TestPolymorphism(Base *p)
{
// 雖然使用的是父類型的指針
// 但虛函數最終會根據對象的真實類型調用。
(*((Vtbl*)p->pvtbl)->pf1)();
}
void TestVtbl()
{
// 子類的一個對象
Derive s;
Base *p = 0;
// 初始化
InitDerive(&s);
p = (Base*)&s;
// 調用Sfoo4
((SVtbl*)p->pvtbl)->pf4("Sfoo4");
// 測試多態
TestPolymorphism((Base*)&s);
}
int main() { TestVtbl(); system("pause"); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 結果: