c印记(三): my_oopc

目录

    • 目录
    • 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 __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语言中还有啥好玩儿的东东可以拿出来唠唠。

你可能感兴趣的:(面向对象,C语言,面向接口,lw-oopc,my-oopc)