zoukankan      html  css  js  c++  java
  • 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参数,并将其初始化。

  • 相关阅读:
    ACM学习历程——POJ 1700 Crossing River(贪心)
    ACM学习历程——POJ 2376 Cleaning Shifts(贪心)
    ACM学习历程——HDU1331 Function Run Fun(锻炼多维dp的打表)
    hadoop-mapreduce-架构概念
    Java-笔记12
    Java-笔记11-复习
    机器学习概述
    hadoop-hdfs-API
    hadoop-
    Java-Project-02
  • 原文地址:https://www.cnblogs.com/bracken/p/3092776.html
Copyright © 2011-2022 走看看