doubango类面向对象研究

  本来对面向对象理解就不深,拿到doubango的代码,感觉无从看起。

  挑个通用的面向对象的实现的代码部分,来探究一下。比如,创建sip message的消息时,会调用tsip_message_create()函数,函数内容如下:

tsip_message_t* tsip_message_create()
{
    return tsk_object_new(tsip_message_def_t, tsip_unknown);
}

  代码里面有两个重要部分,

  1. tsip_message_def_t 是一个由sip模块自己定义的tsk_object_def_s对象。tsk_object_def_s是对象的统一的数据格式,里面必须有对象size,构造函数和析构函数:

typedef struct tsk_object_def_s
{
    //! The size of the object.
    tsk_size_t size;
    //! Pointer to the constructor.
    tsk_object_t*    (* constructor) (tsk_object_t *, va_list *);
    //! Pointer to the destructor.
    tsk_object_t*    (* destructor) (tsk_object_t *);
    //! Pointer to the comparator.
    int        (* comparator) (const tsk_object_t *, const tsk_object_t *);
}
tsk_object_def_t;

  这其中sip自己定义的message对象为:

static const tsk_object_def_t tsip_message_def_s = 
{
    sizeof(tsip_message_t),
    tsip_message_ctor,
    tsip_message_dtor,
    tsk_null
};
const tsk_object_def_t *tsip_message_def_t = &tsip_message_def_s;

  2. 上面可以看出tsip_message_def_t是一个拥有构造函数和析构函数的对象,被传进tsk_object_new函数,这个函数的作用就是根据tsip_message_def_t来分配一块内存区域,并进行初始化。现在看一下tsk_object_new的具体内容:

tsk_object_t* tsk_object_new(const tsk_object_def_t *objdef, ...)
{
    // Do not check "objdef", let the application die if it's null
    tsk_object_t *newobj = tsk_calloc(1, objdef->size);
    if(newobj){
        (*(const tsk_object_def_t **) newobj) = objdef;
        TSK_OBJECT_HEADER(newobj)->refCount = 1;
        if(objdef->constructor){ 
            va_list ap;
            tsk_object_t * newobj_ = newobj;// save
            va_start(ap, objdef);
            newobj = objdef->constructor(newobj, &ap); // must return new
            va_end(ap);

            if(!newobj){ // null if constructor failed to initialized the object
                tsk_free(&newobj_);
            }

#if TSK_DEBUG_OBJECTS
        TSK_DEBUG_INFO("N∞ objects:%d", ++tsk_objects_count);
#endif
        }
        else{
            TSK_DEBUG_WARN("No constructor found.");
        }
    }
    else{
        TSK_DEBUG_ERROR("Failed to create new tsk_object.");
    }

    return newobj;
}

   a. 代码第一行提示不用对objdef的防护。

   b. 代码第二行根据之前传入的sip对象中的size来分配内存。

   c. 代码第四行比较难理解。可以这样考虑,首先不要去想newobj是指向分配好的内存区域的指针,而是将它看作一个普通的void 指针。那么(const tsk_object_def_t **) newobj就会将newobj强制类型转换为一个tsk_object_def_t的指针,这个指针指向了一个tsk_object_def_t的指针。所以解引用newobj就写成*(const tsk_object_def_t **) newobj,它的结果就是tsk_object_def_t的指针。最后,将此指针指向objdef。

   如下图所示,newobj为分配好的内存空间,经过(const tsk_object_def_t **) newobj转换之后,newobj的前4个字节,就变成了一个指向指针的指针,这个指针存储的内容是一个地址,这个地址后来被设置为objdef的地址,代码也就是地四行的(*(const tsk_object_def_t **) newobj) = objdef;

   d. 第五行TSK_OBJECT_HEADER(newobj)->refCount将newobj的下一个位置设置为refCount,即引用计数,并初始化为1.

   e. 第六行到十五行判断是否在对象中有默认构造函数,例如我们的sip message中构造函数为tsip_message_ctor,这个构造函数接受newobj参数,并将其初始化。

 

posted @ 2013-05-22 14:50  brackenbo  阅读(325)  评论(0编辑  收藏  举报