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来说的不同之处:
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语言中还有啥好玩儿的东东可以拿出来唠唠。
- c印记(三): my_oopc
- c印记(四): 递归
- c印记(五):数组
- c印记(一):面向对象
- c印记(二):lw_oopc简介
- c印记(七): ini file解析
- c印记(八): ring buffer实现
- c印记(六): 数组与递归联合应用的小游戏
- c印记(十一): 单向链表 list原理与实现
- c印记(十二):队列queue原理与实现
- c印记(十四):跨平台线程封装
- 先留个印记
- 留点印记
- 印记基因
- 人生印记
- c印记(十三):表驱动编程——优美的逻辑优化者
- 逝去的时光印记
- 世界杯半决赛印记
- xshell远程连接自动断开的问题解决办法
- html5 mysql oracle SSM框架源码 SSH maven
- Android网络传输中必用的两个加密算法:MD5 和 RSA
- LeetCode 67 Add Binary(二进制相加)(*)
- 30天自制操作系统第一周(二)
- c印记(三): my_oopc
- Mysql主从复制配置笔记
- JAVA设计模式初探之适配器模式
- Unity 读取 相关
- Android Push Notification实现信息推送使用
- json2xml python script
- BeagleboneBack 从零开始系列之三(如何启动或使用)
- 分布式系统编程,你到哪一级了?
- 谈谈visual studio QTCreator eclipse的远程调试