c印记(三): my_oopc

目录


上一篇介绍了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 __cplusplus
extern "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_INTERFACE

ABS_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_CLASS

CLASS(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_CTOR

ABS_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_CTOR

DTOR(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 __cplusplus
extern "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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值