C语言面向对象的艺术

先来看封装。
所谓封装,通俗地说,就是一个姑娘化了妆,只给你看她想让你看的那一面,至于里面是否刮了骨、垫了东西,不给你看。说到封装就得说隐藏,这是对兄弟概念;其实我理解隐藏是更深的封装,完全不给你看见,而封装可能是犹抱琵琶半遮面。封装在 c++ 语言中有 protected 、 private 关键字在语言层面上支持,而 c 语言中没有这些。c 有结构体( struct ),其实可以实现封装和隐藏。
struct a_private;struct a { int a; ... void (*func)(struct a*); struct a_private * priv;};上面的代码,我们只向前声明结构体 struct a_private ,没人知道它里面具体是什么东西。假如 struct a 对应的头文件是 a.h ,那么把 a_private 的声明放在 a_p.h 中,a.c 文件包含 a_p.h ,那么在实现 struct a 的函数指针 func 时如何使用 struct a_private ,客户程序员根本无须知道。
这样做的好处是显而易见的,除了预定义好的接口,客户程序员完全不需要知道实现细节,即便实现经过重构完全重来,客户程序员也不需要关注,甚至相应的模块连重新编译都不要——因为 a.h 自始至终都没变过。
另外对于某些方法,仅仅是在对象内部使用,它们将采用static修辞把作用范围局限在一个文件的内部:
到现在为止,封装和隐藏就实现了,而且很彻底。
再看继承。
首先c语言中的void指针是非常强大的,不仅可以指向变量而且还可以泛指向任何数据,例如不同类型的变量,函数等。不同变量间的指针只需要强制转换类型就可实现不同类型数据的访问。例如如下代码:
struct parent_class{int a, b;char *str;};struct child_class{struct parent_class p;int a, b;};void func(){struct child_class obj, *obj_ptr;struct parent_class *parent_ptr;obj ptr = &obj;/* 获得父指针 */parent ptr = (struct parent*) &obj;parent ptr- >a = 1;parent ptr- >b = 5;obj ptr- >a = 10;obj ptr- >b = 100;}在上面代码中,注意subobject结构中第一个成员p,这种声明方式代表subobject类型的数据中开始的位置包含一个parent类型的变量。在函数func中obj是一个subobject对象,正向这个结构类型指示的,它前面的数据应该包含一个parent类型的数据。在第17行的强制类型赋值中parent ptr指向了obj变量的首地址,实际上也就是obj变量中的p对象。
好了,现在parent ptr指向的是一个真真实实的parent类型的结构,那么可以按照parent的方式访问其中的成员,当然也包括可以使用和parent结构相关的函数来处理内部数据,因为一个正常的,正确的代码,它是不会越界访问parent结构体以外的数据的。经过这基本的结构体层层相套包含,对象简单的继存关系就体现出来了:父对象放于数据块的最前方,代码中可以通过强制类型转换来获得父对象指针。
最后来看多态。
这里只讲解多态最基本的用法,就是实现改写对象的行为。虚函数与重载涉及比较复杂的底层机制,笔者暂时还没有研究清楚。
多态,就是说用同一的接口代码处理不同的数据。比如说,下面的base_class结构就是一个通用的数据结构,我们也不清楚a是什么数据,vfunc是什么处理函数?但是,我们处理的时候只要调用base_class->vfunc(int a)就可以了。剩下来的事情我们不需要管,因为不同的接口会有不同的函数去处理,我们只要学会调用就可以了。
struct base_class{int a;void (*vfunc)(int a);}void base_class_vfunc(struct base_class *self, int a){assert(self != null);assert(slef- >vfunc != null);self- >vfunc(a);}struct child_class{struct base_class parent;int b;};void child_class_init(struct child_class* self){struct base_class* parent;parent = (struct_base_class*) self;assert(parent != null);parent- >vfunc = child_class_vfunc;}static void child_class_vfunc(struct child_class*self, int a){self- >b = a + 10;}

一份不错的嵌入式C编码规范
XKCON祥控斗轮堆取料机防碰撞控制系统具备实时监控斗轮机的位置、异常报警等功能
ADI: MEMS传感器,下一代导航新选择
ios10.3.1对比之前版本,网友:真是甩了一大截
vivoZ1Pro在印度上市
C语言面向对象的艺术
华为mate10什么时候上市?华为mate10最新消息:可以对抗iphone8的巨无霸华为mate10,这配置人间少有
小米MIX4或将采用90Hz刷新率的屏幕和40W快速充电
LG Display扭亏为盈!第一季或再出现亏损
压电式加速度传感器原理与选型
基于硬件的真正直流RMS 测量应用设计解决方案
碳纤维结构性能对单向复合材料压缩性能的影响
!售MARCONI 2955B综合测试仪MARCONI 29
磁屏蔽插件电感的选择小技巧分享
IAR单片机编程软件的使用方法介绍
虹科方案 | 虹科Panorama SCADA平台的HMI功能
中国半导体市场空间大,国外半导体企业纷纷在中国建立合资公司
跟关晓彤学做“自拍小仙女” 她的自拍必杀技你get了吗
KD-211型数码分段开关工作原理图
STM32速成笔记(15)—串口IAP