c印记(三): my_oopc

来源:互联网 发布:阿里云1g空间多少钱 编辑:程序博客网 时间:2024/04/28 00:39

目录

    • 目录
    • 1CLASS
    • 2CTORDTOR
    • 3CLASS_NEWCLASS_DELETE
    • 4OVERRIDE_FUNC_SETTINGIMPLEMENT_FUNC_SETTING
    • 5 完整的my_oopc头文件以及简单的使用例子
    • 6在my_oopc的基础上再次优化ver02
    • 7总结


上一篇介绍了lw_oopc v1.2当中的一些宏定义,以及如何使用这些宏定义,总体来说使用起来还是非常简单的。这一篇既然叫做my_oopc,那么就来说一说优化和增加了一些功能之后的lw_oopc会是什么样子。沿用上一篇的流程,先用表格列举一下my_oopc相对于lw_oopc来说的不同之处:

my_oopc新增 类型 创作目的(为了解决什么问题?) oopc_base_t 结构体 记录当前类的部分信息以及当前类的父类和子类中此结构的地址 CLASS_NEW 宏 用于方便的创建一个类的对象 CLASS_DELETE 宏 用于方便的销毁一个类的对象 OVERRIDE_FUNC_SETTING 宏 用于给父类中被子类继承的函数指针赋值 IMPLEMENT_FUNC_SETTING 宏 用于给当前类实现的接口中的函数指针赋值

1、CLASS

lw_oopc中的CLASS宏比较简单,基本上就是声明了创建/销毁对象,构造/析构对象等函数以及typedef一个结构体。 这样是比较简洁,且不会有性能和空间上的浪费。但这也就表明了,其功能的单一和薄弱。
比如lw_oopc当中的CLASS虽然有继承的实现,但在销毁对象的时候必须使用子类的delete函数,并不能如c++般,即便是拿到基类的对象指针,也能对对象进行销毁动作。所以在my_oopc当中会牺牲一点点的
空间来存放子类和基类的相关信息,并牺牲一点点性能来更好的销毁对象。

废话就不多说了,咱先来看看my_oopc中CLASS宏的定义:

#define CLASS(type)                 \typedef struct type type;           \type* type##_new(OOPC_CTOR_PARAM);  \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_CLASS oopc_base_t __obj;};

从这组宏定义可以看出,与lw_oopc基本相同,只是在结构体的末尾多了一个__obj这样的结构体变量,
其声明如下:

typedef int(*class_dtor_f)(void* classhd);typedef struct oopc_base_s {    unsigned int isDeleted;/* 记录当前类的对象是否已经被释放了 */    const char* name;/*记录类的名字*/    void* cthis; /*记录对象的地址*/    class_dtor_f dtor; /*析构函数*/    struct oopc_base_s* parent; /*记录父类对象的oopc_base_t结构的地址(无父类此为NULL)*/    struct oopc_base_s* child;  /*记录子类对象的oopc_base_t结构的地址(无子类此为NULL)*/}oopc_base_t;

它其实是一个双链表会记录当前类的对象的一些信息,并记录当前类的子类对象以及父类对象的信息结构体的地址。在32位的系统上,其消耗的内存为 24 字节。 从这个结构体中还可以看出一个细节, 那就是这里是使用回调函数(class_dtor_f dtor)来实现对象的析构,这样就可以不需 要依赖类名匹配来调用析构函数了。ABS_CLASS的定义和CLASS一样都将会包含oopc_base_t结构体, 而INTERFACE的定义和lw_oopc中的一样(因为其不会构建/析构)。

2、CTOR/DTOR

  • CTOR的定义与lw_oopc中的定义也大致相同,都是定义对象创建函数,为对象分配内存,并调用类的构造函数初始化对象,只不过多了对oopc_base_t结构体的初始化部分;
#define CTOR(type)                          \    type* type##_new(OOPC_CTOR_PARAM) {                 \    struct type *cthis;                                 \    cthis = (struct type*)OOPC_MALLOC(sizeof(struct type), #type, file, line);   \    if (!cthis){                                        \        return 0;                                       \    }                                                   \    memset(cthis, 0, sizeof(*cthis));                   \    cthis->__obj.name = #type;                          \    cthis->__obj.isDeleted = OOPC_FALSE;                \    type##_ctor(cthis);                                 \    return cthis;                                       \ }                                                      \                                                        \void type##_ctor(type* cthis) {cthis->__obj.cthis = cthis;#define END_CTOR }

从上面的宏可以看出,其并没有对oopc_base_t结构体中的parent和child指针进行赋值,因为默认情况下,此两个值都应该是NULL,即一个类即没有父类,也没有子类。对这两个指针进行赋值的动作是在SUPER_CTOR宏中进行的,表明当前类有父类,也同时表明当前类的父类有子类(有点儿绕),其宏定义如下:

#define SUPER_CTOR(father) \    father##_ctor(SUPER_PTR(cthis, father)); \    (cthis->##father).__obj.child = &(cthis->__obj); \    cthis->__obj.parent = &((cthis->##father).__obj)

3、CLASS_NEW/CLASS_DELETE

在上一篇中,lw_oopc创建一个类的对象,都是直接调用声明类的时候声明的创建对象的函数,也就是说创建不同的类的对象的时候需要调用不同的函数。如:

Fish* fish = Fish_new();    // 创建鱼对象Dog* dog = Dog_new();       // 创建狗对象

这样其实并不太方便,感觉上也会比较混乱一点。然后就是关于销毁对象的接口,在上一篇中因为比较简单,类的内部并未进行内存分配,故而并未使用类的析构函数,而是直接调用的一个释放内存的函数来进行对象的销毁。这样也是不够灵活和安全的。所以笔者在my_oopc中就新增了两个了宏CLASS_NEW/CLASS_DELETE来分别实现类的对象的创建和销毁。其具体的宏定义如下:

#define CLASS_NEW(type)  \    type##_new(__FILE__, __LINE__)

对于CLASS_NEW宏的实现是非常简单的,就是通过传入类的名字来匹配创建对象的函数。当然这里并不是最优的做法,因为这里也是调用了每个类都会定义一个的创建对象的函数,但事实上这些函数所做的事情就本上都是一样的(只是类的名字不一样),然而以目前的这种实现方式,每定义一个类就需要实现一个创建对象的函数,这些代码都是冗余的。后续笔者将会说明这些进一步的优化(就好比my_oopc ver 0.2)。

#define CLASS_DELETE(classPtr)   \    do{const char* name = NULL;  \       oopc_base_t* obj = &((classPtr)->__obj);   \       while (obj->child != NULL) obj = obj->child; /*find last child,because last child need destruct first */  \       name = obj->name;     \       do{if ((obj->isDeleted == OOPC_FALSE) && obj->dtor){if (obj->dtor(obj->cthis) != OOPC_TRUE)break;}      \           obj->isDeleted = OOPC_TRUE;           \           if (!obj->parent){ OOPC_DELETE(classPtr, name); /*free instance memory*/ break; }    \           obj = obj->parent;                    \       } while (obj != NULL);/*destruct from last child to last parent */  \    } while (0)

因为对象销毁的顺序是先子类,后基类,所以这里就需要通过一个循环,找到最末端的子类,然后依次先子类后父类的运行对象的析构函数,当所有析构函数都运行结束之后才会真正的释放对象的内存。

4、OVERRIDE_FUNC_SETTING/IMPLEMENT_FUNC_SETTING

my_oopc中在lw_oopc的FUNCTION_SETTING宏基础上新增了两个宏,用于对INTERFACE和ABS_CLASS中定义的方法指针进行赋值,其定义如下:

#define OVERRIDE_FUNC_SETTING(father, f1, f2) cthis->##father##.f1 = f2#define IMPLEMENT_FUNC_SETTING OVERRIDE_FUNC_SETTING

5、 完整的my_oopc头文件以及简单的使用例子

#ifndef __MY_OOPC_H__#define __MY_OOPC_H__#ifdef __cplusplusextern "C"{#endif/*************************************************************************** * * macro define * ***************************************************************************/#if defined(HAVE_STD_OFFSETOF)#define USE_STD_OFFSETOF#else#define USE_USER_DEF_OFFSETOF#endif//////////////////////////////////////////////////////////////////////////#define OOPC_MALLOC(size, typeName, fileName, lineNum) malloc(size)#define OOPC_FREE  free#define OOPC_DELETE(cthis, name) printf("delete obj(%s), class(%s)\n",#cthis, ##name); OOPC_FREE(cthis)#define OOPC_CTOR_PARAM  const char* file, int line#define OOPC_TRUE  1#define OOPC_FALSE 0//////////////////////////////////////////////////////////////////////////#if defined(USE_STD_OFFSETOF)#include <stddef.h>#define OOPC_OFFSETOF offsetof#elif defined(USE_USER_DEF_OFFSETOF)#define OOPC_OFFSETOF(s,m) (size_t)&(((s*)0)->m)#endif/*************************************************************************** * * data struct declaration * ***************************************************************************/typedef int(*class_dtor_f)(void* classhd);typedef struct oopc_base_s {    unsigned int isDeleted;    const char* name;    void* cthis;    class_dtor_f dtor;    struct oopc_base_s* parent;    struct oopc_base_s* child;}oopc_base_t;/*************************************************************************** * * API declaration * ***************************************************************************////////////////////////////////////////////////////////////////////////////** * interface declaration,this just define function,cann't define data member */#define INTERFACE(type)             \typedef struct type type;           \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_INTERFACE };/** * abstract class macro declaration */#define ABS_CLASS(type)             \typedef struct type type;           \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_ABS_CLASS oopc_base_t __obj;};/** * class macro declaration */#define CLASS(type)                 \typedef struct type type;           \type* type##_new(OOPC_CTOR_PARAM);  \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_CLASS oopc_base_t __obj;};///////////////////////////////////////////////////////////////////////////*data/interface type: private, public */#define PROTECTED_DATA(classType)   struct classType##ProtectData{#define END_PROTECTED_DATA     }protectData;///////////////////////////////////////////////////////////////////////////** constructor function define*/#define CTOR(type)                          \    type* type##_new(OOPC_CTOR_PARAM) {                 \    struct type *cthis;                                 \    cthis = (struct type*)OOPC_MALLOC(sizeof(struct type), #type, file, line);   \    if (!cthis){                                        \        return 0;                                       \    }                                                   \    memset(cthis, 0, sizeof(*cthis));                   \    cthis->__obj.name = #type;                          \    cthis->__obj.isDeleted = OOPC_FALSE;                \    type##_ctor(cthis);                                 \    return cthis;                                       \ }                                                      \                                                        \void type##_ctor(type* cthis) {cthis->__obj.cthis = cthis;#define END_CTOR }/** *destructor function define *note: if define destructor, then must call DTOR_FUNC_SETTING to set destructor function *see also DTOR_FUNC_SETTING */#define DTOR(type)      \    int type##_dtor(void* t){type* cthis = (type*)t;#define END_DTOR return OOPC_TRUE;}/** abstract class constructor function define */#define ABS_CTOR(type)              \    void type##_ctor(type* cthis) {cthis->__obj.cthis = cthis;#define END_ABS_CTOR }#define ABS_DTOR     DTOR#define END_ABS_DTOR END_DTOR//////////////////////////////////////////////////////////////////////////#define FUNCTION_SETTING(f1, f2)    cthis->f1 = f2#define OVERRIDE_FUNC_SETTING(father, f1, f2) cthis->##father##.f1 = f2#define IMPLEMENT_FUNC_SETTING OVERRIDE_FUNC_SETTING/** *if defined destructor, then must call this macro to set destructor function *see also DTOR */#define DTOR_FUNC_SETTING(type)     cthis->__obj.dtor = type##_dtor#define ABS_DTOR_FUNC_SETTING  DTOR_FUNC_SETTING#define PROTECTED_FUNC_SETTING(f1, f2) OVERRIDE_FUNC_SETTING(protectData, f1, f2)//////////////////////////////////////////////////////////////////////////#define IMPLEMENTS(type)    struct type type#define EXTENDS(type)       struct type type//////////////////////////////////////////////////////////////////////////#define SUPER_PTR(cthis, father) ((father*)(&(cthis->##father)))#define SUPER_PTR_2(cthis, father, grandfather) \    SUPER_PTR(SUPER_PTR(cthis, father), grandfather)#define SUPER_PTR_3(cthis, father, grandfather, greatgrandfather) \    SUPER_PTR(SUPER_PTR_2(cthis, father, grandfather), greatgrandfather)/**!!!!!!!note PROTECTE just inner use or inherit class!!!!!!!!!!!!!*/#ifdef __cplusplus /*c++ have scope limit */#define PROTECTED_DATA_TYPE(classType)   struct classType::classType##ProtectData#else#define PROTECTED_DATA_TYPE(classType)   struct classType##ProtectData#endif#define PROTECTED_PTR(cthis, classType) ((PROTECTED_DATA_TYPE(classType)*)(&((cthis)->##protectData)))#define SUPER_PROTECTED_PTR(cthis, father) PROTECTED_PTR(SUPER_PTR(cthis, father), father)//////////////////////////////////////////////////////////////////////////#define SUPER_CTOR(father) \    father##_ctor(SUPER_PTR(cthis, father)); \    (cthis->##father).__obj.child = &(cthis->__obj); \    cthis->__obj.parent = &((cthis->##father).__obj)//////////////////////////////////////////////////////////////////////////#define SUB_PTR(selfptr, self, child) \    ((child*)((char*)selfptr - OOPC_OFFSETOF(child, self)))#define SUB_PTR_2(selfptr, self, child, grandchild) \    SUB_PTR(SUB_PTR(selfptr, self, child), child, grandchild)#define SUB_PTR_3(selfptr, self, child, grandchild, greatgrandchild) \    SUB_PTR(SUB_PTR_2(selfptr, self, child, grandchild), grandchild, greatgrandchild)#define INHERIT_FROM(father, cthis, field)  cthis->father.field///////////////////////////////////////////////////////////////////////////** create a class instance */#define CLASS_NEW(type)  \    type##_new(__FILE__, __LINE__)/** release a class instance */#define CLASS_DELETE(classPtr)   \    do{const char* name = NULL;  \       oopc_base_t* obj = &((classPtr)->__obj);   \       while (obj->child != NULL) obj = obj->child; /*find last child,because last child need destruct first */  \       name = obj->name;     \       do{if ((obj->isDeleted == OOPC_FALSE) && obj->dtor){if (obj->dtor(obj->cthis) != OOPC_TRUE)break;}      \           obj->isDeleted = OOPC_TRUE;           \           if (!obj->parent){ OOPC_DELETE(classPtr, name); /*free instance memory*/ break; }    \           obj = obj->parent;                    \       } while (obj != NULL);/*destruct from last child to last parent */  \    } while (0)#ifdef __cplusplus}#endif#endif //end of __MY_OOPC_H__

还是以各种动物为例子:

/* 接口,基类,子类的声明 */INTERFACE(IMoveable)    void(*move)(IMoveable* t);     // Move行为END_INTERFACEABS_CLASS(Animal)    char name[128];     // 动物的昵称(假设小于128个字符)    int age;            // 动物的年龄    void(*setName)(Animal* t, const char* name);   // 设置动物的昵称    void(*setAge)(Animal* t, int age);             // 设置动物的年龄     void(*sayHello)(Animal* t);                    // 动物打招呼    void(*eat)(Animal* t);                         // 动物都会吃(抽象方法,由子类实现)    void(*breathe)(Animal* t);                     // 动物都会呼吸(抽象方法,由子类实现)    void(*init)(Animal* t, const char* name, int age); // 初始化昵称和年龄END_ABS_CLASSCLASS(Fish)    EXTENDS(Animal);        // 继承Animal抽象类    IMPLEMENTS(IMoveable);  // 实现IMoveable接口    void(*init)(Fish* t, const char* name, int age);END_CLASS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*具体定义*//* 设置动物的昵称 */void Animal_setName(Animal* t, const char* name){    // 这里假定name小于128个字符,为简化示例代码,不做保护(产品代码中不要这样写)    strcpy(t->name, name);}/* 设置动物的年龄 */void Animal_setAge(Animal* t, int age){    t->age = age;}/* 动物和我们打招呼 */void Animal_sayHello(Animal* t){    LOGD("Hello! 我是%s,今年%d岁了!\n", t->name, t->age);}/* 初始化动物的昵称和年龄 */void Animal_init(Animal* t, const char* name, int age){    t->setName(t, name);    t->setAge(t, age);}ABS_CTOR(Animal)/*animal 类的构造函数*/ABS_DTOR_FUNC_SETTING(Animal);FUNCTION_SETTING(setName, Animal_setName);FUNCTION_SETTING(setAge, Animal_setAge);FUNCTION_SETTING(sayHello, Animal_sayHello);FUNCTION_SETTING(init, Animal_init);END_ABS_CTORABS_DTOR(Animal)/*animal 类的析构函数*/    LOGD("Animal base class dtor\n");END_ABS_DTOR/* 鱼的吃行为 */void Fish_eat(Animal* t){    LOGD("鱼吃水草!\n");}/* 鱼的呼吸行为 */void Fish_breathe(Animal* t){    LOGD("鱼用鳃呼吸!\n");}/* 鱼的移动行为 */void Fish_move(IMoveable* t){    LOGD("鱼在水里游!\n");}/* 初始化鱼的昵称和年龄 */void Fish_init(Fish* t, const char* name, int age){    Animal* animal = SUPER_PTR(t, Animal);    animal->setName(animal, name);    animal->setAge(animal, age);}CTOR(Fish) /*fish 类的构造函数 */SUPER_CTOR(Animal);DTOR_FUNC_SETTING(Fish);OVERRIDE_FUNC_SETTING(Animal, eat, Fish_eat);OVERRIDE_FUNC_SETTING(Animal, breathe, Fish_breathe);IMPLEMENT_FUNC_SETTING(IMoveable, move, Fish_move);FUNCTION_SETTING(init, Fish_init);END_CTORDTOR(Fish)/*fish 类的析构函数*/    LOGD("fish class dtor\n");END_DTOR/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*应用实例*/int main(int argc, char* argv[]){    Animal* animal = NULL;    IMoveable* moveObj = NULL;    Fish* fish = CLASS_NEW(Fish);     // 创建鱼对象        fish->init(fish, "小鲤鱼", 1);     // 初始化鱼对象的昵称为:小鲤鱼,年龄为:1岁        animal = SUPER_PTR(fish, Animal); // 将fish指针转型为Animal类型指针    //打印动物容器内的动物信息    animal->eat(animal);    animal->breathe(animal);    animal->sayHello(animal);    //打印可移动物体容器内的可移动物体移动方式的信息    moveObj->move(moveObj);    CLASS_DELETE(fish); /*使用当前类的对象指针销毁fish对象*/    fish = CLASS_NEW(Fish);    // 创建鱼对象    fish->init(fish, "小鲤鱼", 1);     // 初始化鱼对象的昵称为:小鲤鱼,年龄为:1岁        animal = SUPER_PTR(fish, Animal); // 将fish指针转型为Animal类型指针    CLASS_DELETE(animal); /*使用当前类的父类的对象指针销毁fish对象*/    return 0;}

6、在my_oopc的基础上再次优化(ver0.2)

如第3节中所说的,对于类的对象创建函数部分还可以再次优化,以节省编译后的二进制size。同理,销毁对象的宏(CLASS_DELETE)也可以进行一些优化。

  • 对于类的构造函数的修改,需要将参数type* t 改为void* t,且在CLASS宏中不需要再声明类对象的 创建函数type* type##_new(OOPC_CTOR_PARAM):
#define CLASS(type)                 \typedef struct type type;           \void type##_ctor(void* t);          \int type##_dtor(void* t);           \struct type{#define END_CLASS oopc_base_t __obj;};/** constructor function define*/#define CTOR(type)                          \void type##_ctor(void* t) {type* cthis = (type*)t; cthis->__obj.cthis = cthis;
  • 然后就是就是对CLASS_NEW和CLASS_DELETE宏的更改:
#define CLASS_NEW(type)  \    (type*)oopcCreate(__FILE__, __LINE__, #type, sizeof(type), type##_ctor)  #define CLASS_DELETE(classPtr)   \    oopcDestory(__FILE__, __LINE__, classPtr, sizeof(*(classPtr)))

在这里创建对象和销毁对象都是通过函数去完成的,这两个的定义如下:

void* oopcCreate(const char* file, int line, const char* className, unsigned int size, void(*ctor)(void* t)){    void* cthis = OOPC_MALLOC(size, className, file, line);    if (!cthis)    {            return 0;                                         }                                                   memset(cthis, 0, size);    oopc_base_t* _obj = (oopc_base_t*)((char*)cthis + size - sizeof(oopc_base_t));   _obj->name = className; /*todo,使用数组或分配内存保存类名*/   _obj->isDeleted = OOPC_FALSE;   ctor(cthis);   return cthis;}void oopcDestory(const char* file, int line, void* classPtr, unsigned int size){    const char* name = NULL;     oopc_base_t* obj = (oopc_base_t*)((char*)classPtr + size - sizeof(oopc_base_t));     while (obj->child != NULL)    {        obj = obj->child; /*find last child,because last child need destruct first */     }    name = obj->name;    do    {        if ((obj->isDeleted == OOPC_FALSE) && obj->dtor)        {            if (obj->dtor(obj->cthis) != OOPC_TRUE)            {                break;             }        }        obj->isDeleted = OOPC_TRUE;         if (!obj->parent)        {            OOPC_DELETE(classPtr, name); /*free instance memory*/             break;         }        obj = obj->parent;                 } while (obj != NULL);/*destruct from last child to last parent */  \}

这样虽然然后类的对象的创建和销毁都是使用统一的函数,走统一的流程,但为了不让编译之后的二进制膨胀,就只能将上面这个两个函数放在 .c文件中,也就是这套my_oopc除了my_oopc.h这样一个头文 件之外还需要增加一个my_oopc.c文件用于存放函数定义。虽然这增加了一个文件,但是有效的减少了用户代码编译后的二进制膨胀,且在函数里面实现这些流程也增加了类型安全和可调试性。

具体应用的例子和第5节中的例子是一样的,就不在多讲了,现在就来看看my_oopc(ver0.2)的完整实现:

  • my_oopc.h
#ifndef __MY_OOPC_H__#define __MY_OOPC_H__#ifdef __cplusplusextern "C"{#endif/*************************************************************************** * * macro define * ***************************************************************************/#if defined(HAVE_STD_OFFSETOF)#define USE_STD_OFFSETOF#else#define USE_USER_DEF_OFFSETOF#endif//////////////////////////////////////////////////////////////////////////#define OOPC_MALLOC(size, typeName, fileName, lineNum) malloc(size)#define OOPC_FREE  free#define OOPC_DELETE(cthis, name) printf("delete obj(%s), class(%s)\n",#cthis, ##name); OOPC_FREE(cthis)#define OOPC_CTOR_PARAM  const char* file, int line#define OOPC_TRUE  1#define OOPC_FALSE 0//////////////////////////////////////////////////////////////////////////#if defined(USE_STD_OFFSETOF)#include <stddef.h>#define OOPC_OFFSETOF offsetof#elif defined(USE_USER_DEF_OFFSETOF)#define OOPC_OFFSETOF(s,m) (size_t)&(((s*)0)->m)#endif/*************************************************************************** * * data struct declaration * ***************************************************************************/typedef int(*class_dtor_f)(void* classhd);typedef struct oopc_base_s {    unsigned int isDeleted;    const char* name;    void* cthis;    class_dtor_f dtor;    struct oopc_base_s* parent;    struct oopc_base_s* child;}oopc_base_t;/*************************************************************************** * * API declaration * ***************************************************************************////////////////////////////////////////////////////////////////////////////** * interface declaration,this just define function,cann't define data member */#define INTERFACE(type)             \typedef struct type type;           \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_INTERFACE };/** * abstract class declaration,this class */#define ABS_CLASS(type)             \typedef struct type type;           \void type##_ctor(type* t);          \int type##_dtor(void* t);           \struct type{#define END_ABS_CLASS oopc_base_t __obj;};/** * class declaration,this class */#define CLASS(type)                 \typedef struct type type;           \void type##_ctor(void* t);          \int type##_dtor(void* t);           \struct type{#define END_CLASS oopc_base_t __obj;};///////////////////////////////////////////////////////////////////////////*data/interface type: private, public */#define PROTECTED_DATA(classType)   struct classType##ProtectData{#define END_PROTECTED_DATA     }protectData;///////////////////////////////////////////////////////////////////////////** constructor function define*/#define CTOR(type)                          \void type##_ctor(void* t) {type* cthis = (type*)t; cthis->__obj.cthis = cthis;#define END_CTOR }/** *destructor function define *note: if define destructor, then must call DTOR_FUNC_SETTING to set destructor function *see also DTOR_FUNC_SETTING */#define DTOR(type)      \    int type##_dtor(void* t){type* cthis = (type*)t;#define END_DTOR return OOPC_TRUE;}/** abstract class constructor function define */#define ABS_CTOR(type)              \    void type##_ctor(type* cthis) {cthis->__obj.cthis = cthis;#define END_ABS_CTOR }#define ABS_DTOR     DTOR#define END_ABS_DTOR END_DTOR//////////////////////////////////////////////////////////////////////////#define FUNCTION_SETTING(f1, f2)    cthis->f1 = f2#define OVERRIDE_FUNC_SETTING(father, f1, f2) cthis->##father##.f1 = f2#define IMPLEMENT_FUNC_SETTING OVERRIDE_FUNC_SETTING/** *if defined destructor, then must call this macro to set destructor function *see also DTOR */#define DTOR_FUNC_SETTING(type)     cthis->__obj.dtor = type##_dtor#define ABS_DTOR_FUNC_SETTING  DTOR_FUNC_SETTING#define PROTECTED_FUNC_SETTING(f1, f2) OVERRIDE_FUNC_SETTING(protectData, f1, f2)//////////////////////////////////////////////////////////////////////////#define IMPLEMENTS(type)    struct type type#define EXTENDS(type)       struct type type//////////////////////////////////////////////////////////////////////////#define SUPER_PTR(cthis, father) ((father*)(&(cthis->##father)))#define SUPER_PTR_2(cthis, father, grandfather) \    SUPER_PTR(SUPER_PTR(cthis, father), grandfather)#define SUPER_PTR_3(cthis, father, grandfather, greatgrandfather) \    SUPER_PTR(SUPER_PTR_2(cthis, father, grandfather), greatgrandfather)/**!!!!!!!note PROTECTE just inner use or inherit class!!!!!!!!!!!!!*/#ifdef __cplusplus /*c++ have scope limit */#define PROTECTED_DATA_TYPE(classType)   struct classType::classType##ProtectData#else#define PROTECTED_DATA_TYPE(classType)   struct classType##ProtectData#endif#define PROTECTED_PTR(cthis, classType) ((PROTECTED_DATA_TYPE(classType)*)(&((cthis)->##protectData)))#define SUPER_PROTECTED_PTR(cthis, father) PROTECTED_PTR(SUPER_PTR(cthis, father), father)//////////////////////////////////////////////////////////////////////////#define SUPER_CTOR(father) \    father##_ctor(SUPER_PTR(cthis, father)); \    (cthis->##father).__obj.child = &(cthis->__obj); \    cthis->__obj.parent = &((cthis->##father).__obj)//////////////////////////////////////////////////////////////////////////#define SUB_PTR(selfptr, self, child) \    ((child*)((char*)selfptr - OOPC_OFFSETOF(child, self)))#define SUB_PTR_2(selfptr, self, child, grandchild) \    SUB_PTR(SUB_PTR(selfptr, self, child), child, grandchild)#define SUB_PTR_3(selfptr, self, child, grandchild, greatgrandchild) \    SUB_PTR(SUB_PTR_2(selfptr, self, child, grandchild), grandchild, greatgrandchild)#define INHERIT_FROM(father, cthis, field)  cthis->father.field///////////////////////////////////////////////////////////////////////////** create a class instance */#define CLASS_NEW(type)  \    (type*)oopcCreate(__FILE__, __LINE__, #type, sizeof(type), type##_ctor)  /** release a class instance */#define CLASS_DELETE(classPtr)   \    oopcDestory(__FILE__, __LINE__, classPtr, sizeof(*(classPtr)))void* oopcCreate(const char* file, int line, const char* className, unsigned int size, void(*ctor)(void* t));void oopcDestory(const char* file, int line, void* classPtr, unsigned int size);#ifdef __cplusplus}#endif#endif //end of __MY_OOPC_H__
  • my_oopc.c
#include "my_oopc.h"void* oopcCreate(const char* file, int line, const char* className, unsigned int size, void(*ctor)(void* t)){    void* cthis = OOPC_MALLOC(size, className, file, line);    if (!cthis)    {            return 0;                                         }                                                   memset(cthis, 0, size);    oopc_base_t* _obj = (oopc_base_t*)((char*)cthis + size - sizeof(oopc_base_t));   _obj->name = className; /*todo,使用数组或分配内存保存类名*/   _obj->isDeleted = OOPC_FALSE;   ctor(cthis);   return cthis;}void oopcDestory(const char* file, int line, void* classPtr, unsigned int size){    const char* name = NULL;     oopc_base_t* obj = (oopc_base_t*)((char*)classPtr + size - sizeof(oopc_base_t));     while (obj->child != NULL)    {        obj = obj->child; /*find last child,because last child need destruct first */     }    name = obj->name;    do    {        if ((obj->isDeleted == OOPC_FALSE) && obj->dtor)        {            if (obj->dtor(obj->cthis) != OOPC_TRUE)            {                break;             }        }        obj->isDeleted = OOPC_TRUE;         if (!obj->parent)        {            OOPC_DELETE(classPtr, name); /*free instance memory*/             break;         }        obj = obj->parent;                 } while (obj != NULL);/*destruct from last child to last parent */  \}

7、总结

my_oopc是为了更方便的使用和调试在lw_oopc基础上优化,更改,增加了部分东西,当然这远远没有到极致,应该还可以做更多的优化。但这毕竟只是使用c语言去模拟面向对象和面向接口编程,如果花太多时间和精力去让这些宏,函数等更加完善,就有些得不偿失了,而且这也会增加其复杂度,再使用上可能不见得就会好上多少,一不小心可能就掉进了过度设计的陷阱。

至此关于c语言模拟面向对象/接口编程和lw_oopc宏以及基于lw_oopc宏优化的my_oopc等等东西的部分就结束了。后续再看看c语言中还有啥好玩儿的东东可以拿出来唠唠。

0 0
原创粉丝点击