c语言 面向对象 构造,C语言面向对象的构造

C++虚函数表实现与结构体尺寸探讨
本文详细介绍了C++中虚函数表的结构和使用,包括如何定义和初始化虚函数表,以及如何通过宏进行操作。同时,通过测试用例展示了结构体的内存布局,讨论了虚函数表的大小和成员变量的位置。此外,还对比了静态全局虚函数表和动态分配虚函数表的区别。

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

将虚函数表存储在结构后面,避免使用全局,静态的存储区

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值