1.对象定义:



对象的定义包含对象的主要函数,大小,以及引用计数。


必须的函数包括 构造函数,析构函数,比较函数


对象的创建包含两个过程:1). 在堆上分配动态内存。这就是为什么必须填写对象大小的原因 ,对象分配内存后,对象的所有成员会被初始化成0,


                                                2).接下来就调用构造函数初始化对象的成员属性。



2. 对象的析构


 对象的析构包含两个过程,1)释放对象的成员,对象的析构函数负责此任务,2)释放对象本身。



3.构造函数


构造函数只负责初始化而不会申请对象内存,对象传给构造函数前已经分配内存。



4.析构函数


析构函数会释放对象的成员,不会释放对象本身,析构函数必须返回对象本身,以便于调用者可以释放对象。


5.引用计数


引用计数用来作垃圾回收,一个定义良好的对象应该包含一个引用计数,用于指示有多少个指向实际对象的引用。


当一个对象被创建时,引用计数初始化为1.当你手动调用ref 及unref此值自动加1减1,当引用计数为0时对象被毁收。


6.继承


我们知道,C语言不支持继承,但是,任何C语言结构本身能够强制指向其第一个元素的指针,这样就可以达到继承的目的。




理论的东西网上一大片,我就不扯了,直接上代码:


spd_obj.h 源码:


#ifndef SPD_OBJECT_H

#define SPD_OBJECT_H


#include <stdarg.h>

#include <stdio.h>



#ifdef __cplusplus extern "C" {


typedef void spd_obj_t;


typedef struct {

    // ! The size of the object

    size_t size;

    spd_obj_t* (*constructor) (spd_obj_t *, va_list *);

    spd_obj_t* (*destructor) (spd_obj_t *);

    int (*comparator) (const spd_obj_t *, const spd_obj_t *);

} spd_obj_def_t;


/*  release obj */

#define SPD_OBJ_SAFE_FREE(obj) if(obj) spd_obj_unref(obj),obj = NULL;


/* base class as is */

#define SPD_OBJ_DECLARE \

    const void* __base__; \

    size_t refCount;


/* get the definition of the object */

#define SPD_OBJ_DEF(obj) (const (spd_obj_def_t *)obj)


spd_obj_t *spd_obj_new(const  spd_obj_def_t *, ...);

size_t *spd_obj_sizeof(const spd_obj_def_t *, ...);

spd_obj_t *spd_obj_ref(spd_obj_t *);

spd_obj_t *spd_obj_unref(spd_obj_t *);

void spd_obj_delete(spd_obj_t *);

spd_obj_t *spd_obj_cmp(const spd_obj_def_t *, const spd_obj_def_t *);

size_t *spd_obj_get_refcount(spd_obj_t *);


}


#endif



spd_obj.c 源码:



#include "spd_obj.h"


typedef struct  {

    const void *base;

    int refCount;

} spd_obj_header_t;


#define SPD_OBJ_HEADER_DEF(obj) (const (spd_obj_header_t*))



spd_obj_t *spd_obj_new(const spd_obj_def_t *obj,...)

{

    spd_obj_t *newobj = spd_calloc(1, obj->size);

    if(newobj) {

        (*(const spd_obj_def_t **) newobj) = obj;

        SPD_OBJ_HEADER_DEF(obj)->refCount = 1;

        if(obj->constructor) {

            va_list ap;

            va_start(ap, obj);

            newobj = obj->constructor(&newobj, &ap);

            va_end(ap);

        } else {

            spd_log(LOG_WARNING, "must set constructor\n");

        }

    } else {

        spd_log(LOG_ERROR, "failed to alloc\n");

    }

    return newobj;

}


size_t spd_obj_sizeof(const spd_obj_t *obj)

{

    const spd_obj_def_t **objdef = (const spd_obj_def_t **)obj;

    if(objdef && *objdef) {

        return (*objdef->size;

    } else {

        spd_log(LOG_ERROR, "NULL OBJ\n");

        return 0;

    }

}


int spd_obj_cmp(const spd_obj_t *obj1, const spd_obj_t *obj2)

{

    const spd_obj_def_t **objdef = (const spd_obj_def_t**)obj2;

    if(objdef && *objdef && objdef->comparator) {

        return objdef->comparator(obj1, obj2);

    }

    return -1;

}


spd_obj_t *spd_obj_ref(spd_obj_t *obj)

{

    spd_obj_def_t *objhdr = SPD_OBJ_HEADER_DEF(obj);

    if(objhdr && objhdr->refCount) {

        objhdr->refCount++;

        return obj;

    }

    return NULL;

}


spd_obj_t *spd_obj_unref(spd_obj_t *obj)

{

    if(obj) {

        spd_obj_header_t *objhdr = SPD_OBJ_HEADER_DEF(obj);

        if(objhdr->refCount) {

            if(!--objhdr->refCount) {

                spd_obj_delete(obj);

                return NULL;

            }

        } else {

            return NULL;

        }

    }

    return obj;

}


size_t spd_obj_get_refcount(spd_obj_t *obj)

{

    return obj ? SPD_OBJ_HEADER_DEF(obj)->refCount : 0;

}


void spd_obj_delete(spd_obj_t *obj)

{

    const spd_obj_def_t **objdef = obj;

    if(obj && *obj) {

        if((*obj)->destructor) { /* destructor only delete member*/

            obj = (objdef)->destructor(obj);

        } else {

            spd_log(LOG_ERROR, "No destructor found\n");

        }

        free(obj); /* release obj itself */

    }

}





测试代码:


test_obj.c


#include "spd_obj.h"


typedef struct {

    SPD_OBJ_DECLARE; /*base class , this is must */


    const *name;

    struct animal_t *pig;

} animal_t;


/* dog is a type of animal*/

typedef struct {

    struct animal_t* animal; /* super class */

    char *type;

} dog_t;


/*constructor */

static spd_obj_t* animal_create(spd_obj_t *obj, va_list *app)

{

    animal_t *ani = obj;

    if(ani) {

        ani->name = spd_strdup(va_arg(*app, const char *);

    }

    return obj;

}


/* destructor */

static spd_obj_t* animal_destroy(spd_obj_t *obj)

{

    animal_t *ani = obj;

    if(ani) {

        spd_free(ani->name);

        spd_obj_unref(ani->pig);


    }

    return obj;

}


static spd_obj_t* animal_cmp(spd_obj_t *obj1, spd_obj_t*obj2)

{

    const animal_t *p1 = obj1;

    const animal_t *p2 = obj2;


    int ret;

    if((ret = strcasecmp(p1->name, p2->name))) {

        return ret;

    }

    /* they are all pig ? :-) */

    if((ret = spd_obj_cmp(p1->pig, p2->pig))) {

        return ret;

    }


    return 0; /* same */

}


static const spd_obj_def_t animal_def_t = {

    sizeof(animal_t),

    animal_create,

    animal_destroy,

    animal_cmp

};


/* the single interface you see */

#define ANIMAL_CREATE(name) spd_obj_new(&animal_def_t, (const char *)name)


static void test_animal()

{

    animal_t *candy = ANIMAL_CREATE("Candy");

    candy->pig = ANIMAL_CREATE("Sony");

    SPD_OBJ_SAFE_FREE(candy);

    

}


int main(int argc ,char *argv[])

{

    test_animal();


    return 0;

}