如何用C实现一个类以及些许设计模式
2014-09-22 20:46
483 查看
在一些开源项目中,结构体中有成员变量,成员函数指针,还有结构体,归属上是子结构体,行为上却是父结构体,这就算是没有访问控制的继承和封装。关于多态,可以通过注册函数来覆盖父结构体的方法。构造和析构也可以通过初始化和去初始化函数来实现,注册和反注册也在此进行。
实例程序
parent.h
parent.c
child.h
child.c
以上代码的健壮性很差,只是抛砖引玉,其实函数指针的使用还是比较危险的,需要良好的控制方法
访问控制不太好实现,对于面向过程的C,一般得靠人力进行访问控制的检查;当需要增加统一的功能时,可以直接在父结构体就行修改。注意是在子结构体中包含父结构体
有了类的基础,就可以实现一些设计模式
比如策略模式,可以用两个只有函数指针的父结构体,分别代表独立的不同方法,子结构体初始化的时候可以指向其中一个。
比如单件模式,可以通过精心设计的静态变量和静态方法来实现
当然,对于大部分能使用OO语言的场合,还是使用OO语言。但是在某些特殊的场合,比如Linux内核以及嵌入式编程中,适当引入OO思想对于扩展性还是很有帮助的
实例程序
parent.h
#ifndef PARENT_H #include <stdio.h> struct parent { int a; //成员变量 int (*test)(void); //成员函数 void (*fly)(void); void (*display)(const struct parent par_d); /*......*/ }; void par_init(struct parent *); //初始化函数 static int par_num; #endif // PARENT_H
parent.c
#ifndef PARENT_C #include "parent.h" static int test(void) { return 0; } static void fly(void) { printf("I can fly\n"); } static void display(const struct parent par_d) { printf("the par->a is %d\nthe par->test is 0x%x\nthe par->fly is 0x%x\n", par_d.a, par_d.test, par_d.fly); } void par_init(struct parent *par) //初始化函数 { par->a = 1; par->display = display; //不必去初始化,方便测试 par->test = test; par->fly = fly; } void par_deinit(struct parent *par) //去初始化函数 { par->a = 0; par->test = NULL; par->fly = NULL; } #endif // PARENT_C
child.h
#ifndef CHILD_H #include "parent.h" struct child { struct parent parentA; void (*display)(const struct child cli_d); }; void A_init(struct child *); void A_deinit(struct child *); #endif // CHILD_H
child.c
#ifndef CHILD_C #include "child.h" static int CoverMethod[32] = {0}; enum MethodName { TEST = 0, /*......*/ }; #define PRINTNULL(x){ \ if(x) printf("the %s is not NULL\n", #x); \ else if(!x) printf("the %s is NULL\n", #x); \ } static int test(void) { return 1; } static void display(const struct child cli_d) //模仿操作法"<<"重载 { printf("the child is 0x%x\n", &cli_d); const struct parent par_d = cli_d.parentA; printf("the parent is 0x%x\n", &par_d); cli_d.parentA.display(par_d); } void A_init(struct child *cli) //初始化,并注册函数指针 { par_num++; par_init(&(cli->parentA)); cli->display = display; //操作符重载模拟不必去初始化,方便测试 if(NULL != (void *)test) { CoverMethod[TEST] = (int)cli->parentA.test; cli->parentA.test = test; //覆盖父结构体的方法 } /*......其他需要覆盖的方法*/ } void A_deinit(struct child *cli) //去初始化,反注册 { if(NULL != (void *)test) { cli->parentA.test = CoverMethod[TEST]; //还原父结构体的方法 } /*......其他需要还原的方法*/ par_num--; if(!par_num) par_deinit(&(cli->parentA)); } void main() { struct child childA; A_init(&childA); const struct child cli_d = childA; childA.display(cli_d); printf("the a is %d, the result is %d\n", childA.parentA.a, childA.parentA.test()); childA.parentA.fly(); par_num = 2; //测试用 A_deinit(&childA); printf("the a is %d, the result is %d\n", childA.parentA.a, childA.parentA.test()); childA.parentA.fly(); PRINTNULL(childA.parentA.test); PRINTNULL(childA.parentA.fly); par_num = 1; //测试用 A_deinit(&childA); childA.display(cli_d); PRINTNULL(childA.parentA.test); PRINTNULL(childA.parentA.fly); } #endif // CHILD_C
以上代码的健壮性很差,只是抛砖引玉,其实函数指针的使用还是比较危险的,需要良好的控制方法
访问控制不太好实现,对于面向过程的C,一般得靠人力进行访问控制的检查;当需要增加统一的功能时,可以直接在父结构体就行修改。注意是在子结构体中包含父结构体
有了类的基础,就可以实现一些设计模式
比如策略模式,可以用两个只有函数指针的父结构体,分别代表独立的不同方法,子结构体初始化的时候可以指向其中一个。
比如单件模式,可以通过精心设计的静态变量和静态方法来实现
当然,对于大部分能使用OO语言的场合,还是使用OO语言。但是在某些特殊的场合,比如Linux内核以及嵌入式编程中,适当引入OO思想对于扩展性还是很有帮助的
相关文章推荐
- 如何使用三层架构设计模式去完整的实现一个功能?
- 设计模式-观察者模式,以及如何使用观察者来为app实现即时通讯功能
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
- DAO设计模式---实现一个简单的注册(中)
- 2009 年8 月6号 学习 uml、ea、设计模式以及如何使用它们进行分析、设计
- 一个通用的单元测试框架的思考和设计06-实现篇-自动管理测试数据-如何临时关闭数据外键约束
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件(来自微软官网)
- Silverlight开发中的疑难杂症-控件设计篇-如何实现一个NumericBox(下)
- Ubuntu - 在只安装了Ubuntu一个系统的时候如何进入grub界面以及single模式从而修改root口令
- 用JSP+Servlet+JavaBean模式实现一个简单的登录网页设计(JSP+Tomcat+MySQL)
- 如何用设计模式变相实现类的多继承?
- C#基础:抽象类和抽象方法实现多态以及简单工厂设计模式的语法
- state设计模式学习, 一个C++的实现
- DAO设计模式---实现一个简单的注册(下)
- 一个通用的单元测试框架的思考和设计07-实现篇-自动管理测试数据-如何为自增长主键id赋值
- 【转帖】如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件
- Silverlight开发中的疑难杂症-控件设计篇-如何实现一个NumericBox(上)
- 正在学设计模式呵,转载一篇如何保证一个窗体的实例运行