四. 如何构造一个对象
我们用下面的结构来描述一个对象:
typedef struct _ClassType
{
char* name; /*对象名,唯一*/
int object_size;/*对象大小,创建实列时分配内存要用到*/
int class_size; /*全部虚函数大小,如sizeof(CObjectClass)*/
void* vclass; /*虚函数指针*/
void (*InitClassCallback)(void*); /*给对象的虚函数赋值*/
void (*InitObjectCallback)(void*);/*对象实例化时,给实例成员赋初值,有点类似构造函数*/
struct _ClassType* parent; /*父对象*/
struct _ClassType* next; /*单向链表,指向下一对象*/
}ClassType;
#define [MAX_CLASS_NUM 128
static ClassType classes[MAX_CLASS_NUM]; /*对象池*/
static ClassType *used_classes = NULL;
static ClassType *free_classes = NULL;
这里只定义了128个对象,数目可能修改或者改成动态分配。
初始化,全部链接到空闲链表中。
void InitObjectLib(void)
{
int i;
memset(classes, 0, sizeof(ClassType)*MAX_CLASS_NUM);
for( i=0;i<MAX_CLASS_NUM-1;i++ )
{
classes[i].next = &(classes[i+1]);
}
free_classes = &(classes[0]);
}
这个函数既是获取对象的虚函数指针,也是注册对象。
这里要注意type为static,一个对象只注册一次,下次获取时直接取type。
RegisterClassType()第一个参数为对象的描述信息,第二个参数为父对象的
函数指针,我们来看一下它的定义:
#define TOP_OBJECT_TYPE 0
#define BASE_OBJECT_TYPE GetObjectType()
因为CObject为基对象,它没有父对象,所以这里第二个参数为0(TOP_OBJECT_TYPE)。
现在假设有一个CObject子对象CSubObject,那么注册它时应该这样写:
type = RegisterClassType(&classinfo, BASE_OBJECT_TYPE);
由此可能看到,这里其实是一个递归:当注册CSubOject里会用到参数BASE_OBJECT_TYPE,
既GetObjectType(),这样就可以把CObject也注册上。
简单的说:如果C继承于B,B继承于A,现在假设A、B还未注册,当注册C时,通过递归
也能把B、A注册上。
int GetObjectType(void)
{
static int type = 0;
if( type==0 )
{
static ClassInfo classinfo =
{
"OBJECT", /*对象名,唯一*/
sizeof(CObject),
sizeof(CObjectClass),
(pInitObjectCallback)InitObject,
(pInitClassCallback)InitObjectClass,
};
type = RegisterClassType(&classinfo, TOP_OBJECT_TYPE);
}
return type;
}
我们再来看一看InitObject和InitObjectClass,
static void InitObjectClass(CObjectClass *vclass)
{
if(vclass==NULL)
return;
vclass->destory = DestoryObject;/*对虚函数赋值*/
}
static void InitObject(CObject *object)
{
if(object==NULL)
return;
object->ref_counter = 1;
}
这两个函数在GetObjectType()被传进去,那么又是在哪儿被调用的呢?
让我们看RegisterClassType()
int RegisterClassType(ClassInfo *classinfo, int parent_type)
{
int type = 0;
ClassDesc *current, *parent;
parent = (ClassType *)parent_type;
if( classinfo->name==NULL )
{
TRACE("RegisterClassType(): class name is NULL\n");
return type;
}
/*检查是否有对象名重复*/
current = used_classes;
while(current)
{
if(strcmp(current->name, classinfo->name)==0 )
{
TRACE("RegisterClassType(): class name is redefined\n");
unlock();
return type;
}
current = current->next;
}
/*创建对象*/
current = free_classes;
if(current)
{
free_classes = free_classes->next;
current->name = classinfo->name;
current->parent = parent;
current->class_size = classinfo->class_size;
current->InitClassCallback = classinfo->InitClassCallback;
current->InitObjectCallback = classinfo->InitObjectCallback;
current->vclass = malloc(current->class_size);
if( current->vclass==NULL )
{
TRACE("RegisterClassType(): malloc vclass failed\n");
}
memset( current->vclass, 0, current->class_size);
current->vclass->class_type = (int)current;
if( parent )/*子对象的虚函数全部指向父对象的虚函数*/
{
memcpy(current->vclass, parent->vclass, parent->class_size);
}
对子对象新添加的虚函数赋值,也可以对继承于父对象的虚函数重赋值。
if( current->InitClassCallback )
current->InitClassCallback(current->vclass);
链接到对象池中
current->next = used_classes;
used_classes = current;
}
else
{
TRACE("RegisterClassType(): ERROR, no class in class pool\n");
}
type = (int)current; 注意:type为ClassType类型的指针。
return type;
}
五. 创建对象的实例
CObject *NewObject(void) /*创建一个实例*/
{
return NewClassType(BASE_OBJECT_TYPE);
}
void *NewClassType(int class_type)
{
ClassType *pclass = NULL;
void *object = NULL;
if( pclass==0 )
return NULL;
pclass = (ClassType*)class_type;
/*为实例分配内存空间*/
object = (CObject*)malloc(pclass->object_size);
if( object )
{
/*实例的虚函数指针指向它的对象的虚函数指针*/
((CObject*)object)->vclass = pclass->vclass;
/*调用父对象的初始化函数,这个函数是递归函数,
先初始化基对象,再初始化子对象,再初始化子子对象...*/
InitParentObject(pclass, object);
}
return object;
}
static void InitParentObject(ClassType *current, void *object)
{
if( current )
{
if( current->parent )
InitParentObject(current->parent, object);
if( current->InitObjectCallback )
current->InitObjectCallback(object);
}
}