為什么要用C來模擬面向對象的機制,在實際的工作中我們往往在感慨一些面向對象的經典設計模式由於C語言的限制無法使用,其實通過簡單的模擬面向對象的行為,在C語言中也可以使用這些模式。
1:類的構建
類描述了所創建的對象共同的屬性和方法。我們在一個源文件中通過把數據和操作進行適當的組織來完成類的模擬。
/*類的數據*/
typedef struct SQUARE_S SQUARE_T; struct SQUARE_S { void (*draw)(void*); int sideLen; };
/*類的方法*/
static void draw(void* pObj) { SQUARE_T* pSqr = (SQUARE_T*)pObj; printf("Draw Square len is %d\n",pSqr->sideLen); }
如上所示,一個正方形的類我們用一個結構體SQUARE_T來表示正方形的屬性,draw是其中的一個方法。
2:類的封裝性
類的封裝一般要求對細節的隱藏並且提供指定的方法供調用者使用,在SQUARE這個類中,sideLen是圖形的細節,只需要提供一個draw接口給調用者。因此在提供給外部調用的接口頭文件中構建如下的接口。
typedef struct SHAPE_S SHAPE; struct SHAPE_S { void (*draw)(void*); };
通過定義不同的數據結構來達到數據隱藏的目的,如下圖所示,對外接口中只能看到draw,內部實現中可以看到draw和sideLen。
3:多態的模擬
多態無疑是面向對象語言的很重要的一個機制,很多面向對象的設計模式都是以多態為基礎,C語言並不支持多態,導致很多設計模式都無法直接使用。
一個典型的多態例子,通過聲明一個SHAPE接口,根據實例化對象類型的不同,pShape在運行時動態的表現不同的行為。
SHAPE* pShape = NULL; //一個形狀接口 pShape = (SHAPE*)Ins(SQUARE,2); //實例化為一個正方形 pShape->draw(pShape); //pShape表現為正方形的行為
多態機制的實現依賴函數指針,在每個類的構造函數中把相關接口用具體的函數地址填充,這樣在實例化一個對象的時候我們才綁定了其具體的操作,也就是所謂的動態綁定。
/*每個類的構造函數*/ static void* Constructor(void* pObj,va_list* pData) { SQUARE_T* pSquare = (SQUARE_T*)pObj; pSquare->draw = draw; //具體行為的填充 pSquare->sideLen = va_arg(*pData,int); return pObj; }
4:對象的創建
有了類,我們需要實例化為可以運行的對象,實例化主要的工作是分配內存、動態綁定、數據初始化等工作。
void* Ins(const void* pClass,...) { CLASS* pCls = NULL; void* pObj = NULL; va_list vaList = NULL; pCls = (CLASS* )pClass; pObj = malloc(pCls->classSize); memset(pObj,0,pCls->classSize); va_start(vaList,pClass); pObj = pCls->Constructor(pObj,&vaList); return pObj;
}
轉載請注明原始出處:http://www.cnblogs.com/chencheng/archive/2012/12/22/2825692.html