doubango ANSI-C 对象编程的实现方法
来源:互联网 发布:野性美的意思知乎 编辑:程序博客网 时间:2024/05/29 15:25
doubango 3GPP IMS/LTE Framework v1.0.0
Programmer’s Guide
正如你知道的,C语言不是一个面向对象的语言。今天,OOP(面向对象编程)是编写精心设计的软件的最好方式。
在这份文档中“被定义的对象”是指一个特殊的C语言结构体。本文中的所有功能是tinySAK项目的一部分。为了解释如何定义对象及如何使用对象,我会使用一个基于“人”的对象的例子。“人”对象被声明是这样的:
typedef struct person_s{TSK_DECLARE_OBJECT; /* Mandatory */char* name;struct person_s* girlfriend;}person_t;
对象定义可以被视为一个类的定义。该定义包括对象的必须具备(强制性)的功能,对象的大小和一个引用计数器。强制性的功能包括:构造函数,析构函数和比较函数。C结构体通过在其体内的TSK_DECLARE_OBJECT宏#define为对象。
对象定义的指针应指向一个结构体 tsk_object_def_s。
typedef struct tsk_object_def_s{//! The size of the object.size_t size;//! Pointer to the constructor.tsk_object_t*(* constructor) (tsk_object_t *, va_list *);//! Pointer to the destructor.tsk_object_t*(* destructor) (tsk_object_t *);//! Pointer to the comparator.int(*comparator) (const tsk_object_t *, const tsk_object_t *);}tsk_object_def_t;
创建一个对象分为两个阶段。第一阶段是动态在堆上分配对象; 这就是为什么在对象定义结构内它的大小是强制性的原因。当一个新的对象是在堆上分配,其所有成员(char*,void*,int,long...)将被清零。在第二阶段,将新创建的对象通过调用提供的构造函数初始化。为了执行这两个阶段,你应该调用tsk_object_new()或tsk_object_new_2()。
该对象被销毁分两个阶段进行。第一阶段释放其成员(void*,char* ...)。它的析构函数是负责这项任务的。在第二阶段中,对象本身被销毁。因为对象不能销毁自己,你应使用tsk_object_unref或tsk_object_delete,执行这两个阶段。接下来的部分对这两个函数之间的差异进行了解释。
下面是如何声明一个对象定义的例子:
//(Object defnition) static const tsk_object_def_t person_def_t = { sizeof(person_t), person_ctor, person_dtor, person_cmp}构造函数是只负责初始化,并不会分配对象。当传递给构造方法,对象已经被分配。
下面是一个例子:
// (constructor)static tsk_object_t* person_ctor(tsk_object_t * self, va_list * app){ person_t *person = self; if(person){ person->name = tsk_strdup(va_arg(*app, const char *)); } return self; }
析构函数会释放该对象的成员,并不会破坏对象本身(第一阶段)。析构函数必须返回一个指针允许调用者执行第二阶段。
// (destructor) static tsk_object_t * person_dtor(tsk_object_t * self) { person_t *person = self; if(person){ TSK_FREE(person->name);tsk_object_unref(person->girlfriend); } return self; }
比较函数是用来比较两个定义的对象。比较的对象应具有相同的定义(或类型)。
// (comparator)static int person_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2) { const person_t *p1 = _p1; const person_t *p1 = _p2;int ret;// do they have the same name?if((ret = tsk_stricmp(p1->name, p2->name))){return ret;}// do they have the same girlfriend?if((ret = tsk_object_cmp(p1->girlfriend, p2->girlfriend))){return ret;}// they are the samereturn 0; }
引用计数用来模拟垃圾收集。每个被定义的对象包含一个引用计数器的字段,这表明有多少对象对该对象进行引用。
当一个对象被创建(见下文)计数器的值被初始化为1,这是自动完成的,你不用做任何事情。计数器加1,当你调用tsk_object_ref和递减(1)当你调用tsk_object_unref。当计数器的值达到零,然后对象被回收(释放)。
正如你认为的那样,ANSI-C是不支持继承的。因为任何C结构可以强制转换为它的第一个元素的指针,继承可以这样实现:
#include "tsk.h"// (a student is a person)typedef struct student_s{struct person_s* person; // Must be the first elementchar* school;}student_t;// (as a student is a person you can do)student_t* s;((person_t*)s)->name = tsk_strdup("bob");因为person_t是个定义的对象,那么student_t也是。
一旦声明了对象的定义以及实现了对象所有的强制性功能,它可以这样被使用:
// creates a person: will call the constructorperson_t* bob = tsk_object_new(&person_def_t, "bob");// creates bob's girlfriendbob->girlfriend = tsk_object_new(&person_def_t, "alice");// deletes bob: will delete both bob and bob's girlfriend field by calling their destructorstsk_object_unref(bob);由于很难记住构造函数需要哪个参数(As it’s hard to guest which parameters the construct expects),一般我们用宏或函数来帮助。宏定义是这样的:
// create a person#define PERSON_CREATE(name)tsk_object_new(&person_def_t, (const char*)name)由于析构函数有固定的参数,有一个共同的宏来销毁所有定义的对象。 TSK_OBJECT_SAFE_FREE()可用来销毁任何对象。只有当对象的引用计数减1并等于零时,对象将被释放。在所有情况下(释放或不释放)的指针值将设置为NULL。
上面的例子可以写成这样:
#include "tsk.h"// create a person: will call the constructorperson_t* bob = PERSON_CREATE("bob");// create bob's girlfriendbob->girlfriend = PERSON_CREATE("alice");// delete bob: will delete both bob and bob's girlfriend field by calling their destructorsTSK_OBJECT_SAFE_FREE(bob);
- doubango ANSI-C 对象编程的实现方法
- ANSI-C面向对象编程翻译-序言
- 用c语言进行“面向对象编程”------学习doubango源码心得------阿冬专栏!!!
- ANSI C字符串相关的实现
- 顺序栈的实现(ANSI C)
- 链式栈的实现(ANSI C)
- ANSI C文件编程实例
- ANSI C的标准
- Objective-C 编程语言(3) 定义类---分配并初始化对象,init方法的返回值,初始化方法的实现
- Objective-C 编程语言(3) 定义类---分配并初始化对象,init方法的返回值,初始化方法的实现
- 2个开源的Websocket的ANSI C实现
- 单循环链表结构的实现(ANSI C)
- 双循环链表的实现(ANSI C)
- ANSI X9.19 MAC算法的C语言实现
- ANSI-C面向对象编程翻译:第一章 抽象数据类型——信息隐藏
- ANSI-C面向对象编程翻译:第二章 动态连接——通用函数
- C的对象编程
- cgic:用于CGI编程的ANSI C库---cgic在C语言下的编程
- linux shell编程if语句内判断参数详解
- 虚拟机中GUEST OS时钟(TIMEKEEP)问题的探讨
- 窗口设置最顶端,全屏
- hdu3268
- 安卓各种资源介绍及使用方法以及工程各文件夹的介绍
- doubango ANSI-C 对象编程的实现方法
- Android兼容性测试框架(CTS)手册
- C++ XML解析之TinyXML篇
- 如何去掉或修改DeDeCMS二级栏目标题title中的斜杠(/)?
- 智能查询功能lucene使用情况及遇到的问题
- 一些关于头文件的理解
- android编译生成的out目录结构分析
- 详解DDoS攻击技术的方法
- WPF 资源 总结