1. define the structure of virtual function table
- #ifndef __INTERFACE_H__
- #define __INTERFACE_H__
- //定义一个虚函数表名称
- #define VTBL(iname) iname##Vtbl
- //定义虚函数表结构
- #define QINTERFACE(iname) struct _##iname{/
- struct VTBL(iname) *pvt;/
- };/
- struct VTBL(iname)
- //定义一个虚函数表变量
- #define DECLARE_VTBL(iname) iname vt##iname;
- //获取虚函数表的指针
- #define GET_PVTBL(p,iname) ( (iname *)(void *)p )->pvt
- //初始化虚函数表
- #define INIT_VTBL(p,iname,vt) ( GET_PVTBL(p,iname) = (VTBL(iname) *)(void *)&vt)
- //声明基类
- #define DECLARE_IBASE(iname)/
- int (*AddRef) (iname *);/
- int (*Release)(iname *);
- //下面是测试用例
- typedef struct _IList IList;
- QINTERFACE(IList)
- {
- DECLARE_IBASE(IList)
- int (*SetActive)(IList *p, int bSet);
- };
- #define ILIST_AddRef(p) GET_PVTBL( (p), IList)->AddRef( (p) )
- #define ILIST_Release(p) GET_PVTBL( (p), IList)->Release( (p) )
- #define ILIST_SetActive(p,b) GET_PVTBL( (p), IList)->SetActive( (p) , (b) )
- #define OBJECT(n)/
- typedef struct n n;/
- struct n
- /*################################################################################*/
- //定义一个虚函数表名称
- #define AEEVTBL(iname) iname##Vtbl
- //定义虚函数表结构
- #define AEEINTERFACE(iname)/
- typedef struct AEEVTBL(iname) AEEVTBL(iname);/
- struct AEEVTBL(iname)
- //获取虚函数表指针
- #define AEEGETPVTBL(p,iname) ( *( AEEVTBL(iname) **) (void*)p)
- //初始化虚函数表
- #define AEEINITVTBL(p,iname,vt) ( AEEGETPVTBL( (p) ,iname) = (AEEVTBL(iname)*)(&vt) )
- //整合了AEEINTERFACE
- #define AEEINTERFACE_DEFINE(iname)/
- typedef struct iname iname;/
- AEEINTERFACE(iname){/
- INHERIT_##iname(iname)/
- };
- //下面是测试用例
- typedef struct TestType TestType;
- #define INHERTT_TestType(TestType)/
- int (*AddRef)(TestType*);/
- int (*Release)(TestType*);
- AEEINTERFACE(TestType)
- {
- INHERTT_TestType(TestType)
- int (*SetActive)(TestType *p, int bSet);
- };
- #define ITESTTYPE_AddRef(p) (AEEGETPVTBL(p, TestType)->AddRef(p)
- #define ITESTTYPE_Release(p) (AEEGETPVTBL(p, TestType)->Release(p)
- #define ITESTTYPE_SetActive(p,b) (AEEGETPVTBL(p, TestType)->SetActive(p,b)
- #endif
2. define the structure of "class"
- #include "interface.h"
- #include <iostream>
- using namespace std;
- OBJECT(List)
- {
- DECLARE_VTBL(IList)
- int m_nRef;
- int m_nCap;
- int m_nInc;
- };
- static int List_AddRef(IList* p)
- {
- printf("Call List_AddRef/n");
- return 0;
- }
- static int List_Release(IList* p)
- {
- printf("Call List_Release/n");
- return 0;
- }
- static int List_SetActive(IList* p,int b)
- {
- printf("Call List_SetActive/n");
- return 0;
- }
- static const VTBL(IList) g_ConstVtbl=
- {
- List_AddRef,
- List_Release,
- List_SetActive,
- };
- int TestQInterface()
- {
- List *pme = (List *)malloc(sizeof(List ));
- if(!pme)
- {
- return 1;
- }
- IList *po = (IList*)pme;
- memset(pme, 0x0, sizeof(List));
- INIT_VTBL(pme, IList, g_ConstVtbl);
- pme->m_nRef = 1;
- //virtual table size: 4 Bytes
- printf("virtual table size:%d/n",sizeof(VTBL(IList)));
- //object size
- printf("struct size:%d/n", sizeof(List));
- //member original address
- printf("original address of member:0x%x/n", &pme->m_nRef);
- //object and virtual original address
- printf("address of pointer:0x%x/n", pme);
- //the first member(int)
- printf("value of m_nRef:%d/n", *(int*)((char*)(pme)+4));
- printf("/n");
- printf("/n");
- ILIST_AddRef(po);
- ILIST_Release(po);
- ILIST_SetActive(po, 0);
- printf("/n");
- printf("/n");
- free(pme);
- pme = NULL;
- return 0;
- }
- struct TestType
- {
- AEEVTBL(TestType) *pvt;
- int m_nRef;
- int m_nCap;
- int m_nInc;
- };
- static int TestType_AddRef(TestType* p)
- {
- printf("Call TestType_AddRef/n");
- return 0;
- }
- static int TestType_Release(TestType* p)
- {
- printf("Call TestType_Release/n");
- return 0;
- }
- static int TestType_SetActive(TestType* p,int b)
- {
- printf("Call TestType_SetActive/n");
- return 0;
- }
- static const AEEVTBL(TestType) gTestTypeFuncTbl =
- {
- TestType_AddRef,
- TestType_Release,
- TestType_SetActive,
- };
- int TestAEEInterface()
- {
- TestType*pme = (TestType*)malloc(sizeof(TestType));
- if(!pme)
- {
- return 1;
- }
- AEEVTBL(TestType) *po = ( AEEVTBL(TestType)* )pme;
- memset(pme, 0x0, sizeof(TestType));
- AEEINITVTBL(pme, TestType, gTestTypeFuncTbl);
- //pme->pvt = (AEEVTBL(TestType)*) &gTestTypeFuncTbl;
- pme->m_nRef = 1;
- //virtual table size: 4 Bytes
- printf("virtual table size:%d/n",sizeof(AEEVTBL(TestType)));
- //object size
- printf("struct size:%d/n", sizeof(List));
- //member original address
- printf("original address of member:0x%x/n", &pme->m_nRef);
- //object and virtual original address
- printf("address of pointer:0x%x/n", pme);
- //the first member(int)
- printf("value of m_nRef:%d/n", *(int*)((char*)(pme)+4));
- printf("/n");
- printf("/n");
- TestType_AddRef(pme);
- TestType_Release(pme);
- TestType_SetActive(pme,0);
- printf("/n");
- printf("/n");
- free(pme);
- pme = NULL;
- return 0;
- }
- int main(int argc, char *argv[])
- {
- TestAEEInterface();
- return 0;
- }
- /*
- 之所以为虚函数表申请空间,应该是避免使用全局或者静态的变量来存储虚函数表
- int MyFunc_New(IMyFunc **ppo)
- {
- //分配的内存为数据大小+虚表大小
- CMyFunc *pMe = (CMyFunc *) MALLOC(sizeof(CMyFunc)+sizeof(AEEVTBL(IMyFunc)));
- //使主调函数的指针指向这个对象
- *ppo = (IMyFunc *)pMe;
- //0初始化
- MEMSET(pMe, 0, sizeof(CMyFunc)+sizeof(AEEVTBL(IMyFunc)));
- //设置成员,第二个参数能计算虚表的开始地址,加的1应为偏移了整个结构大小。
- //把虚函数表存储在了结构的后面[struct + vtbl]
- MyFunc_Initialize(pMe, (AEEVTBL(IMyFunc)*)(pMe+1), pIModule, pIShell);
- return SUCCESS;
- }
- //设置成员
- static int MyFunc_Initialize(CMyFunc *pMe, AEEVTBL(IMyFunc) *pvt)
- {
- pMe->pvt = pvt;
- pvt->func1 = ...;
- ...
- } */
3. about the size of structure
1) size of virtual function table
4 bytes
2) size of member variable
0xxxxx --> original address
0xxxxx --> virtual table 4B
0xxxxx --> member 1
0xxxxx --> member 2
0xxxxx --> member 3
4. initialization of stucture.
1) use static global virtual table.
- static const VTBL(IList) g_ConstVtbl=
- {
- List_AddRef,
- List_Release,
- List_SetActive,
- };
2) use dynamic virtual table
CMyFunc *pMe = (CMyFunc *) MALLOC(sizeof(CMyFunc)+sizeof(AEEVTBL(IMyFunc)));
0xxxxx --> original address
0xxxxx --> virtual table 4B
0xxxxx --> member 1
0xxxxx --> member 2
0xxxxx --> member 3
0xxxxx --> original address of virtual table
将虚函数表存储在结构后面,避免使用全局,静态的存储区