剖析C++多型:用C實現簡單多型
怎樣用C語言實現多型,首先想到的應該是去模擬C++的虛擬函式。
在C++中,每一個含有虛擬函式的類,都有一個虛擬函式表。對於類的每一個物件,都有一個指向虛擬函式表的指標。
用C語言模擬這個過程。先考慮最簡單的情況,只含有一個虛擬函式的類,並且只有建構函式,沒有虛解構函式。
假設這個類Base有一個int型別的成員變數val,虛擬函式run(int num)能夠輸出(val+num)的值。它的派生類Derived的結構與它類似,但是函式run(int num)輸出(val*num)的值。
C語言中並沒有類,所以我們用結構體來代替類,用含有指向類的指標的函式來表示類的成員函式。
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
typedef int (*PFUNC)(void*, int); // 函式指標
/*這個宣告引入了 PFUNC 型別作為函式指標的同義字,該函式有個 void* 和 int 型別的引數以及一個 int 型別的返回值。 */
/*基類*/
typedef struct BASE {
PFUNC VIRTUAL;
int val;
} Base;
int BASE_RUN(void* self, int num) {
return ((Base*)self)->val + num;
}
Base* CONS_BASE(int val) {
Base* p = malloc(sizeof(Base));
p->VIRTUAL = BASE_RUN;
p->val = val;
return p;
}
/*派生類*/
typedef struct DERIVED {
PFUNC VIRTUAL;
int val;
} Derived;
int DERIVED_RUN(void* self, int num) {
return ((Derived*)self)->val * num;
}
Derived* CONS_DERIVED(int val) {
Derived* p = malloc(sizeof(Derived));
p->VIRTUAL = DERIVED_RUN;
p->val = val;
return p;
}
/*虛擬函式*/
int run(Base* p, int num) {
return p->VIRTUAL((void*)p, num);
}
int main()
{
Base* base = CONS_BASE(10);
Base* derived = (Base*)CONS_DERIVED(10);
int val_base = run(base, 10);
int val_derived = run(derived, 10);
printf("Base:%d\nDerived:%d\n", val_base, val_derived);
return 0;
}
函式CONS_BASE, CONS_DERIVED返回物件指標,可以看作類的建構函式。函式run可以看作是Base類的成員函式。
通過結構體的定義可以看出,結構體中有一個指向函式的指標VIRTUAL,他的作用類似於虛擬函式表,只不過因為表中只有一個函式,因此省略了表的結構。
在建構函式中,除了初始化val的值,還將函式BASE_RUN、DERIVED_RUN賦值給了函式指標VIRTUAL。當呼叫run時,通過self指標找到函式指標VIRTUAL。雖然self指標是指向Base的指標,但是由於Base與Derived的前4個位元組(32位)都是VIRTUAL指標,所以當基類的指標指向派生類時,VIRTUAL指標指向的也是派生類的成員函式DERIVED_RUN。這樣就實現了簡單的多型。
執行結果如下:
Base:20
Derived:100
成功。
複雜版本的思路:
首先結構體裡指向函式的指標要改成(void**)型別,指向一個虛擬函式表。而虛擬函式表要通過另外的一個函式初始化。各個函式在表中的位置要手動的指定,比如run函式在表中第一位,go函式在表中第二位。當呼叫函式時,首先找到虛擬函式表,再根據不同的編號去找到表中對應位的函式進行呼叫。
可以發現虛擬函式的呼叫比普通的函式呼叫多了一個查表的過程,降低了一點效率。
相關文章
- C++ 多型的實現及原理C++多型
- C++——多型C++多型
- C++多型C++多型
- C++整理16_多型C++多型
- 虛擬函式表-C++多型的實現原理函式C++多型
- 多型 簡單講解多型
- C++(虛擬函式實現多型基本原理)C++函式多型
- 開心檔之C++ 多型C++多型
- C語言實現繼承多型C語言繼承多型
- C++多型之虛擬函式C++多型函式
- [c++] 繼承和多型整理二C++繼承多型
- 什麼是Java多型?如何實現Java多型?Java多型
- Go 如何實現多型Go多型
- 實現多型多對多 幾個注意點多型
- Python 3.6:多型的實現Python多型
- C# 多型性C#多型
- c#——泛型的多種應用C#泛型
- C++ 引用型別簡介C++型別
- C++八股之函式過載與重寫-靜態多型與動態多型C++函式多型
- 用委託者模式實現的多型別Adapter模式多型型別APT
- C++ const void * 型別轉換簡單測試C++型別
- C/C++ Qt TabWidget 實現多窗體建立C++QT
- c++菱形繼承、多型與類記憶體模型C++繼承多型記憶體模型
- 深入理解 C++ 中的多型與檔案操作C++多型
- C++整理17_執行時多型(晚繫結)C++多型
- 詳解C++中的多型和虛擬函式C++多型函式
- IOS多型別Cell的tableView實現iOS多型型別View
- aardio 實現封裝繼承多型封裝繼承多型
- Java多型實現的必要條件Java多型
- 【C/C++】ghost ddl指令碼簡單實現C++指令碼
- c#重寫和多型C#多型
- 簡單談談方法過載和方法重寫(編譯時多型和執行時多型)編譯多型
- 多型~多型
- 多型。多型
- 多型多型
- C++模板函式實現型別推導C++函式型別
- C++:用棧實現反轉連結串列,超簡單!C++
- [MAUI程式設計]介面多型與實現UI程式設計多型
- C++ 一些學習筆記(十二)類和物件-多型C++筆記物件多型