C語言實現多態
首先聲明,大神就不要看了。小弟水平有限。
C++多態是通過虛函數表實現的,類似於JAVA多態的實現方式。關於Java多態的實現方式可以看我之前寫過的一篇不是很完善的文章。從JVM角度看Java多態。
Java和C++不同,Java中所有的實例方法(相對於類方法,或叫靜態方法而言)都是默認為虛函數,之前貌似看到過Java生成的字節碼中,所有實例方法前面都是右virtual關鍵字的。C++中需要顯示聲明virtual之后才是虛函數,虛函數是實現多態的基礎。
今天用C語言實現的多態,是實現一個類似下面的C++代碼:(由於使用QtCreator寫的,所以會有一點兒QT的代碼,可以忽略)
#include <QCoreApplication> #include <iostream> using namespace std; class Base{ public: virtual void eat(){ cout<<"基類在吃飯....."<<endl; } virtual void play(){ cout<<"基類在玩耍....."<<endl; } }; class DeriveA:public Base{ public: void eat(){ cout<<"子類A在吃飯....."<<endl; } }; class DeriveB:public Base{ public: void eat(){ cout<<"子類B在吃飯....."<<endl; } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Base * base; DeriveA dA; DeriveB dB; base = &dA; base->eat(); base->play(); cout<<"---------------------------------------------\n"; base = &dB; base->eat(); base->play(); return a.exec(); }
其中,基類中有兩個虛函數,eat()和play(),兩個派生類中都只重寫了基類的eat()方法。
輸出結果如下圖:
下面用純C語言實現類似的效果。可以用C語言模仿C++的虛函數表。
首先定義兩個函數指針類型:
typedef void (*EatPtr)(); typedef void (*PlayPtr)();
接着模擬虛函數表,虛函數表就是一個元素為虛函數指針的結構體
typedef struct _virtualPtrTable{ EatPtr eat; PlayPtr play; }VPtrTable;
接着定義“基類和派生類”:
typedef struct _base{ VPtrTable vptrTable; int age; }Base; typedef struct _deriveA{ Base base; int age; }DeriveA; typedef struct _deriveB{ Base base; int age; }DeriveB;
接着實現函數,由於C++代碼中,兩個派生類都沒有實現play方法,所以這里派生類的play函數都只是調用基類的函數。。
/** 派生類A的實現函數 **/ void aEat(){ cout<<"子類A在吃飯....."<<endl; } void aPlay(){ basePlay(); } /** 派生類B的實現函數 **/ void bEat(){ cout<<"子類B在吃飯....."<<endl; } void bPlay(){ basePlay(); }
下面是主函數:
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Base *base; DeriveA deriveA; deriveA.base.vptrTable.eat = aEat; deriveA.base.vptrTable.play = aPlay; deriveA.base.age = 40; deriveA.age = 20; DeriveB deriveB; deriveB.base.vptrTable.eat = bEat; deriveB.base.vptrTable.play = bPlay; deriveB.base.age = 40; deriveB.age = 21; base = (Base *)&deriveA; base->vptrTable.eat(); base->vptrTable.play(); cout<<"age:"<<base->age<<endl; cout<<"---------------------------------------------\n"; base = (Base *)&deriveB; base->vptrTable.eat(); base->vptrTable.play(); cout<<"age:"<<base->age<<endl; return a.exec(); }
完整代碼如下:
#include <QCoreApplication> #include <iostream> using namespace std; typedef void (*EatPtr)(); typedef void (*PlayPtr)(); typedef struct _virtualPtrTable{ EatPtr eat; PlayPtr play; }VPtrTable; typedef struct _base{ VPtrTable vptrTable; int age; }Base; typedef struct _deriveA{ Base base; int age; }DeriveA; typedef struct _deriveB{ Base base; int age; }DeriveB; /** 基類的實現函數 **/ void baseEat(){ cout<<"基類在吃飯....."<<endl; } void basePlay(){ cout<<"基類在玩耍....."<<endl; } /** 派生類A的實現函數 **/ void aEat(){ cout<<"子類A在吃飯....."<<endl; } void aPlay(){ basePlay(); } /** 派生類B的實現函數 **/ void bEat(){ cout<<"子類B在吃飯....."<<endl; } void bPlay(){ basePlay(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Base *base; DeriveA deriveA; deriveA.base.vptrTable.eat = aEat; deriveA.base.vptrTable.play = aPlay; deriveA.base.age = 40; deriveA.age = 20; DeriveB deriveB; deriveB.base.vptrTable.eat = bEat; deriveB.base.vptrTable.play = bPlay; deriveB.base.age = 40; deriveB.age = 21; base = (Base *)&deriveA; base->vptrTable.eat(); base->vptrTable.play(); cout<<"age:"<<base->age<<endl; cout<<"---------------------------------------------\n"; base = (Base *)&deriveB; base->vptrTable.eat(); base->vptrTable.play(); cout<<"age:"<<base->age<<endl; return a.exec(); }
運行效果:
寫的比較簡單,歡迎來探討。
如果你覺得有所收獲,記得點贊呀~~