1. define the structure of virtual function table
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
//定义一个虚函数表名称
#define VTBL(iname) iname##Vtbl
//定义虚函数表结构
#define QINTERFACE(iname) struct _##iname{/
structVTBL(iname) *pvt;/
};/
structVTBL(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 *);
//下面是测试用例
typedefstruct_IList IList;
QINTERFACE(IList)
{
DECLARE_IBASE(IList)
int(*SetActive)(IList *p,intbSet);
};
#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)/
typedefstructn n;/
structn
/*################################################################################*/
//定义一个虚函数表名称
#define AEEVTBL(iname) iname##Vtbl
//定义虚函数表结构
#define AEEINTERFACE(iname)/
typedefstructAEEVTBL(iname) AEEVTBL(iname);/
structAEEVTBL(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)/
typedefstructiname iname;/
AEEINTERFACE(iname){/
INHERIT_##iname(iname)/
};
//下面是测试用例
typedefstructTestType TestType;
#define INHERTT_TestType(TestType)/
int(*AddRef)(TestType*);/
int(*Release)(TestType*);
AEEINTERFACE(TestType)
{
INHERTT_TestType(TestType)
int(*SetActive)(TestType *p,intbSet);
};
#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
#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
usingnamespacestd;
OBJECT(List)
{
DECLARE_VTBL(IList)
intm_nRef;
intm_nCap;
intm_nInc;
};
staticintList_AddRef(IList* p)
{
printf("Call List_AddRef/n");
return0;
}
staticintList_Release(IList* p)
{
printf("Call List_Release/n");
return0;
}
staticintList_SetActive(IList* p,intb)
{
printf("Call List_SetActive/n");
return0;
}
staticconstVTBL(IList) g_ConstVtbl=
{
List_AddRef,
List_Release,
List_SetActive,
};
intTestQInterface()
{
List *pme = (List *)malloc(sizeof(List ));
if(!pme)
{
return1;
}
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;
return0;
}
structTestType
{
AEEVTBL(TestType) *pvt;
intm_nRef;
intm_nCap;
intm_nInc;
};
staticintTestType_AddRef(TestType* p)
{
printf("Call TestType_AddRef/n");
return0;
}
staticintTestType_Release(TestType* p)
{
printf("Call TestType_Release/n");
return0;
}
staticintTestType_SetActive(TestType* p,intb)
{
printf("Call TestType_SetActive/n");
return0;
}
staticconstAEEVTBL(TestType) gTestTypeFuncTbl =
{
TestType_AddRef,
TestType_Release,
TestType_SetActive,
};
intTestAEEInterface()
{
TestType*pme = (TestType*)malloc(sizeof(TestType));
if(!pme)
{
return1;
}
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;
return0;
}
intmain(intargc,char*argv[])
{
TestAEEInterface();
return0;
}
/*
之所以为虚函数表申请空间,应该是避免使用全局或者静态的变量来存储虚函数表
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 = ...;
...
} */
#include "interface.h"
#include
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.
staticconstVTBL(IList) g_ConstVtbl=
{
List_AddRef,
List_Release,
List_SetActive,
};
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
将虚函数表存储在结构后面,避免使用全局,静态的存储区
C++虚函数表实现与结构体尺寸探讨
本文详细介绍了C++中虚函数表的结构和使用,包括如何定义和初始化虚函数表,以及如何通过宏进行操作。同时,通过测试用例展示了结构体的内存布局,讨论了虚函数表的大小和成员变量的位置。此外,还对比了静态全局虚函数表和动态分配虚函数表的区别。
760

被折叠的 条评论
为什么被折叠?



