用C实现C++的多态---剖析GTK的"对象" (二)

原创 2006年06月14日 16:58:00

四. 如何构造一个对象
    我们用下面的结构来描述一个对象:
    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);
  }
 }


 

C++对象布局及多态实现

  • 2008年05月12日 20:35
  • 34KB
  • 下载

C/C++:面向对象编程特性:多态(虚函数表原理)

#include #include using namespace std; //定义两个函数指针类型 typedef void(*pFunc)(void); typedef int(*pSum...
  • jiezhj
  • jiezhj
  • 2014年08月05日 14:54
  • 517

面向对象多态c++

  • 2013年04月16日 07:56
  • 436KB
  • 下载

C++ —面向对象之多态的实现与应用

多态 今天我们的主角就是多态了,那么什么多态呢?多态有什么用? 多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程...
  • Dawn_sf
  • Dawn_sf
  • 2017年04月05日 09:49
  • 586

C语言实现C++面向对象语言多态特性

我们知道,C++语言演化过程中,加入了不少新特性,使其成为一门现代高级OO语言。当初C++在上个世纪七十年代末,80年代初时,C++发展刚刚起步,那时C++可以看作C with class,C++编写...

C++对象布局及多态实现的探索(六)

C++对象布局及多态实现的探索(六) 后记   结合前面的讨论,我们可以看到,只要牵涉到了虚继承,在访问父类的成员变量时生成的代码相当的低效,需要通过很多间接的计算来定位成员变量的...
  • ilvu999
  • ilvu999
  • 2012年09月05日 00:14
  • 580

C++对象布局及多态实现的探索

虚函数的类的对象布局(1)     如果类中存在虚函数时,情况会怎样呢?我们知道当一个类中有虚函数时,编译器会为该类产生一个虚函数表,并在它的每一个对象中插入一个指向该虚函数表的指针,通常这个指...
  • kannju
  • kannju
  • 2011年09月01日 15:40
  • 390

C++中的多态在C中如何实现

多态的含义约等同于“同一个方法对于不同类型的输入参数均能做出正确的处理过程,并给出人们所期望获得的结果” C++的多态性是C++实现面向对象技术的基础。具体的说,通过一个指向基类的指针调用虚成员...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用C实现C++的多态---剖析GTK的"对象" (二)
举报原因:
原因补充:

(最多只允许输入30个字)