C语言的对象化模型
面向对象的特征主要包括:
.封装,隐藏内部实现
.继承,复用现有代码
.多态,改写对象行为
采用C语言实现的关键是如何运用C语言本身的特性来实现上述面向对象的特征。1.1  封装
封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该数据的
方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性(对象
能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能
力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者不必
知晓行为实现的细节,只须用设计者提供的消息来访问该对象。
在C语言中,大多数函数的命名方式是动词+名词的形式,例如要获取一个semaphore,会命名
成take_semaphore,重点在take这个动作上。面向对象编程中刚好相反,命名为rt_sem_take,即名词+动词的形式,重点在名词上,体现了一个对象的方法。另外对于某些方法,仅局限在对象内部使用,它们将采用static修辞把作用范围局限在一个文件的内部。通过这样的方式,把一些不想让用户知道的信息屏蔽在封装里,用户只看到了外层的接口,从而形成了面向对象中的最基本的对象封装实现。一般属于某个类的对象会有一个统一的创建,析构过程。
.对象内存数据块已经存在,需要对它进行初始化 – rt_sem_init;
.对象内存数据块还未分配,需要创建并初始化 – rt_sem_create。
可以这么认为,对象的创建(create)是以对象的初始化(init)为基础的,创建动作相比较而言多了个
内存分配的动作。
相对应的两类析构方式:
.由rt_sem_init初始化的semaphore对象 – rt_sem_detach;
.由rt_sem_create创建的semaphore对象 – rt_sem_delete.1.2  继承
继承性是子类自动共享父类之间数据和方法的机制。它由类的派生功能体现。一个类直接继承其
它类的全部描述,同时可修改和扩充。继承具有传递性。继承分为单继承(一个子类只有一父类)
和多重继承(一个类有多个父类,当前RT-Thread的对象系统不能支持)。类的对象是各自封闭的,
如果没继承性机制,则类对象中数据、方法就会出现大量重复。继承不仅支持系统的可重用性,而
且还促进系统的可扩充性。类似的实现代码如下程序清单:
/*  父类  */
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;
}在上面代码中,注意child_class结构中第一个成员p,这种声明方式代表child_class类型的数据中
开始的位置包含一个parent_class类型的变量。在函数func中obj是一个child_class对象,正像这个
结构类型指示的,它前面的数据应该包含一个parent_class类型的数据。在第21行的强制类型赋值
中parent_ptr指向了obj变量的首地址,也就是obj变量中的p对象。好了,现在parent_ptr指向的是
一个真真实实的parent类型的结构,那么可以按照parent的方式访问其中的成员,当然也包括可以
使用和parent结构相关的函数来处理内部数据,因为一个正常的,正确的代码,它是不会越界访
问parent结构体以外的数据。
经过这基本的结构体层层相套包含,对象简单的继存关系就体现出来了:父对象放于数据块的最
前方,代码中可以通过强制类型转换获得父对象指针。1.3  多态对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种
现象称为多态性。利用多态性用户可发送一个通用的信息,而将所有的实现细节都留给接受消息
的对象自行决定,如是,同一消息即可调用不同的方法。例如:抽象设备具备接口统一的读写接口。
串口是设备的一种,也应支持设备的读写。但串口的读写操作是串口所特有的,不应和其他设备
操作完全相同,例如操作串口的操作不应应用于SD卡设备中。多态性的实现受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次
中尽可能高的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的
对象就能给通用消息以不同的响应。对象模型采用结构封装中使用指针的形式达到面向对象中多态的效果,例如:
/*  抽象父类  */
struct  parent_class
{int  a;/*  反映不同类别属性的方法  */void  (*vfunc)(int  a);
}/*  抽象类的方法调用  */
void  parent_class_vfunc(struct  parent_class  *self,  int  a)
{assert(self  !=  NULL);assert(slef->vfunc  !=  NULL);/*  调用对象本身的虚拟函数  */self->vfunc(a);
}/*  继承自parent class的子类  */
struct  child_class
{struct  parent_class  parent;int  b;
};/*  子类的构造函数  */
void  child_class_init(struct  child_class*  self)
{struct  parent_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;
}阅读(4398)| 评论(5)喜欢推荐转载MIDI数据完成实现标准的DTMF信号 海量数据处理方法
最近读者
登录后,您可以在此留下足迹。 liu_jing07
liu_jingzhansh21cn
zhansh21zougang_215
zougang_liuxueuestc
liuxueueshuangyu226@126
shuangyudmlgt123
dmlgt123张俊勇
张俊勇xiaoying1277
xiaoying
热度1037140300
10371403yzfcer
yzfcer关闭
玩LOFTER,免费冲印20张照片,人人有奖!     我要抢>
评论
点击登录|昵称:江苏 泰州
03-19 13:56
songyajun0107
太精彩了!人才啊!受益匪浅啊
回复
广东 佛山
2011-03-27 09:30
双木
我水平还没到,咋办
回复2010-12-30 12:40
woshizhaozigeng
我仿照您的思路写了一个简单的多态例子,不过实现的不好看, 基类里的虚函数参数void  (*vfunc)(struct parent_class *self, int  a);   /包含一个基类类型指针.
下面每个派生类自己的虚函数实现void  (*vfunc)(struct parent_class *self, int  a);   也要包含一个基类的指针.这样写我感觉很难看..
回复2010-12-30 12:40
woshizhaozigeng
struct  parent_class
{int  a; void  (*vfunc)(struct parent_class *self, int  a);   //虚函数
};
struct child_class
{struct parent_class base;void (vfunc_my_implemention)(struct parent_class *self, int a);
};void child_vfunc(struct parent_class *self, int info)
{printf("这是子类实现的虚方法........\n");
}
void init_child_class(struct child_class *self)
{((struct parent_class *)self)->vfunc = child_vfunc;
}
int main()
{struct parent_class *ptrparent_class = NULL;struct child_class c_object;init_child_class(&c_object);ptrparent_class = (struct parent_class *)&c_object;ptrparent_class->vfunc(ptrparent_class, 2);                 //多态return 0;
}
回复2010-12-30 11:54
woshizhaozigeng
你好,您的关于c语言实现实现多态的部分代码实现有问题。。
当用c实现封装里,由于没有编译器的支持,所以每个函数参数要添加一个指向自己的指针struct  child class*self,相当于c++里面的pthis,所以您说的抽象父类的虚函数里面也要添加一个pthis指针,而且要参数要是void*类型的。您说对吗?
/*  抽象父类  */
struct  parent_class
{int  a;/*  反映不同类别属性的方法  */void  (*vfunc)(int  a);         //改正一下. void(*vfunc)(void *self, int a);
}

     Redy的开发语言是C,但在源码中,有很多地方都使用到了面向对象编程的方法,例如:在基本数据类型这一个模块,所有的数据类型都继承robject;在抽象语法树模块,所有的节点都继承astobjct。在linux内核中,也有很多是使用的面向对象方法,在虚拟文件系统,驱动模型中都可以看到。c语言是一种结构化编程语言,以模块工能和处理过程设计为主,实现数据与代码分隔化。面向对象方法论中,核心是类,类是用于创造对象的模板,其三要素为:封装,继承,多态。C语言本身对面向对象的支持很弱,但可以通过一些技巧来实现。下面通过一个具体的实例来说明实现这此技巧。实例介简:在几何中,所有的几何类型都继承父类“形状(shape)”,父类“形状”有两处属性s_type和s_name。其中s_type用于表示该形状所属的类型,s_name用于表于该形状态的名称。而且父类shape还有两个虚接口,一个为shape_area用于返回该形状的面积,一个为shape_perimeter用于返回该形状的周长。所子继承“形状”的子类都必须实现这两个接口。
struct shape;
struct shape_ops
{/*返回几何体的面积*/float (*so_area)(struct shape*); /*返回几何体的周长*/int (*so_perimeter)(struct shape*);
};
struct shape
{int* s_type;char* s_name;struct shape_ops* s_ops; /*虚接口,所有子类必须实现*/
};float shape_area(struct shape* s)  /*求形状面积*/
{return s->s_ops->so_area(s);
}
int shape_perimeter(struct shape* s) /*求周长*/
{return s->s_ops->so_perimeter(s);
}几何体“三角形(triangle)”继承父类“形状”,并且实现了父类的两个虚接口。“三角形”有三条边,分别用t_side_a,t_side_b,t_side_c来表于三条边的长度。
/*三角形*/
struct triangle
{struct shape t_base;int t_side_a;int t_side_b;int t_side_c;
};float triangle_area(struct shape* s)  /*三角形面积,用海伦公式*/
{struct triangle* t=(struct triangle*)s;int a=t->t_side_a;int b=t->t_side_b;int c=t->t_side_c;float p=(a+b+c)/2;return sqrt(p*(p-a)*(p-b)*(p-c));
}
int triangle_perimeter(struct shape* s)  /*三角形周长*/
{struct triangle* t=(struct triangle*)s;int a=t->t_side_a;int b=t->t_side_b;int c=t->t_side_c;return a+b+c;
}
struct shape_ops triangle_ops=    /*对父类虚接口的实现*/
{triangle_area,triangle_perimeter,
};
struct triangle* triangle_create(int a,int b,int c)  /*创建三角形*/
{struct triangle* ret=(struct triangle*)malloc(sizeof (*ret));ret->t_base.s_name="triangle";ret->t_base.s_ops=&triangle_ops;ret->t_side_a=a;ret->t_side_b=b;ret->t_side_c=c;return ret;
}几何体“矩形(rectangle)”继承父类“形状”,同样也实现的父类的两个虚接口。有两个属性r_width和r_height,分别表示矩形的长和宽。
/*矩形*/
struct rectangle
{struct shape r_base;int r_width;int r_height;
};float rectangle_area(struct shape* s)  /*矩形面积*/
{struct rectangle* r=(struct rectangle*)s;return r->r_width*r->r_height;
}
int rectangle_perimeter(struct shape* s)/*矩形周长*/
{struct rectangle* r=(struct rectangle*)s;return (r->r_width+r->r_height)*2;
}
struct shape_ops rectangle_ops=      /*对父类虚接口的实现*/
{rectangle_area,rectangle_perimeter,
};struct rectangle* rectangle_create(int width, int height)  /*创建矩形*/
{struct rectangle* ret=(struct rectangle*)malloc(sizeof(*ret));ret->r_base.s_name="rectangle";ret->r_base.s_ops=&rectangle_ops;ret->r_height=height;ret->r_width=width;return ret;
}
测试代码:
int main()
{struct shape* s[4];s[0]=triangle_create(5,5,4);s[1]=triangle_create(3,4,5);s[2]=rectangle_create(10,12);s[3]=rectangle_create(5,8);int i=0;for(i=0;i<4;i++){float area=shape_area(s[i]);    int perimeter=shape_perimeter(s[i]);char* name=s[i]->s_name;printf("name:%s ,area:%.2f ,perimeter:%d\n",name,area,perimeter);}return 0;
}运行结果:
name:triangle ,area:9.17 ,perimeter:14
name:triangle ,area:6.00 ,perimeter:12
name:rectangle ,area:120.00 ,perimeter:44
name:rectangle ,area:40.00 ,perimeter:26

我谈C语言和面向对象 by 招之前看完骏豪写的《C语言实现面向对象编程》,同时发现最近blog没有高质量的编程系文章orz,于是就一直想写篇东西谈谈语言和设计,,也算是对自己做程序和OOAD的经验教训小结
打好草稿之后发现又长又臭,索性换一种短而快的方式——分节,一来好写,二来免得大家懒得看=_,=
PS:貌似我还欠着n篇游戏特效制作的文章。。。囧首先更正骏豪的几个错误观点:P
1.面向对象和基于对象是两个不完全相同的东西。
基于对象就是类最基本的特征,将数据和方法绑定到一起。
在C这样没有类的语言中可以用一个结构表示一个类的数据,然后在所有与之相关的函数(方法)中传入这个结构(或指针),也能达到同样的效果,典型例子如C标准库的FILE
另外Win32API中采取的是句柄,即用一个数值作为对象的ID,去代替你操作的对象,同样能达到封装数据的目的。
但是这并未达到面向对象的程度面向对象是在基于对象的基础上做到继承和多态,尤其是多态,这是与基于对象的本质区别,也是面向对象与结构化编程最不同的地方
C可以实现多态,方法是定义一个struct,包含若干函数指针,然后由函数指针指向具体的函数以实现多态
然而要真正实现多态,那么需要衍生出很多“周边产品”——运行时类型检查(RTTI,例如C#的is关键字)、反射等等。这点要在C语言实现只能用取巧的办法,例如自动分配类的id然后查id来匹配,或者用宏等等。
具体可以参考GTK,它的编写风格是面向对象,也支持RTTI。所以Windows至少从API的设计看来并不是面向对象。2.C++ is better than C? OO is better than structral programming?
没有面向对象,甚至没有基于对象,我们真的写不出一个大型的程序吗?
我想大部分初学C++的人都会接受这么一种观点:C++是更好的C语言(很不幸连张锋也这么跟我们说。。囧),至少你爱用OO的特性就用,不爱就当它是C来用。
类似地,面向对象(OO)才是王道,结构化编程纯属老土——这样的观点也充斥于很多C++新手甚至是有相当经验的人士当中。
我写这段并非想争论C和C++孰优孰劣。理解如何通过C语言进行高质量编程对程序设计有非常大的帮助,包括面向对象的能力。我先把问题放这:C语言+结构化编程能写高质量的大型程序。问题是怎么写?

用C语言实现面向对象的开发相关推荐

  1. 使用C语言进行面向对象的开发--GObject入门[2]

    转载请注明出处 blog.csdn.net/pingf0 或www.cnblogs.com/pingf" PART 2. 在正式开始GObject的学习之前,还要简单提一下大名鼎鼎的建立在G ...

  2. 使用C语言进行面向对象的开发--GObject入门[5]

    转载请注明出处 blog.csdn.net/pingf0 或www.cnblogs.com/pingf 接上文 这一部分简要介绍下类的析构,或者成为终结. 还是多说几句,也算是对前文的补充 1.生成一 ...

  3. html是面向对象的开发语言,Web开发常用的6大编程语言和优势

    Web前端是互联网时代软件产品研发中不可缺少的一种专业研发角色,所有用户终端产品与视觉和交互有关的部分,都是Web前端工程师的专业领域.Web开发常用的6大编程语言和优势你知道多少,北大青鸟的老师带您 ...

  4. OO开发思想:面向对象的开发方法(Object oriented,OO)

    面向对象的开发方法(Object oriented,OO)认为是好文章吧,拿来分享一下(转载) 面向对象的开发方法(Object oriented,OO) 从事软件开发的工程 师们常常有这样 的体会: ...

  5. 一步步分析-C语言如何面向对象编程

    这是道哥的第009篇原创 一.前言 在嵌入式开发中,C/C++语言是使用最普及的,在C++11版本之前,它们的语法是比较相似的,只不过C++提供了面向对象的编程方式. 虽然C++语言是从C语言发展而来 ...

  6. C语言到嵌入式Linux开发项目指导

    C语言到嵌入式Linux开发项目指导 第一阶段C语言 1.常量与变量,数据类型,数据类型转换,数据输入与输出: 2.C语言运算符,C语言操作符,C语言表达式,表达式优先级: 3.C语言流程控制,分支, ...

  7. c语言uint32_使C语言实现面向对象的三个要素,你掌握了吗?

    编排 | strongerHuang 微信公众号 | strongerHuang 不知道有多少人去了解过语言的发展史,早期C语言的语法功能其实比较简单.随着应用需求和场景的变化,C语言的语法功能在不断 ...

  8. Java基础----JAVA语言的概述和开发环境的搭配

    01 JAVA语言的概述和开发环境的搭配 JAVA语言简介 创始人:詹姆斯.高斯林 历史:起初属于sun公司,由高斯林与其合伙人研发而出,用于在各种移动设备上进行程序开发设计,初始起名为green,后 ...

  9. 为什么要用C语言实现面向对象

    从事嵌入式开发十几年,基本上围绕着这两种编程语言展开,都可以直接操作底层的编程语言,用的越熟练越是感觉工具属性越强.虽然两种编程语言分属于不同的编程思想,用的时间长了觉得差异也不是很大,现在就个人的从 ...

最新文章

  1. scala 定义空的list_18.scala的型变
  2. HttpServlet类简介和简单用法
  3. 山西农业大学c语言答案,作业答案
  4. nginx主模块指令
  5. .NET 时间格式 ----------摘自MSDN
  6. C语言指针用得好犹如神助!这些使用技巧值得收藏
  7. vs2005的webbrowser控件如何接收鼠标事件
  8. python从入门到精通 pdf 完整超清版-Python从入门到精通PDF高清完整版免费下载|百度云盘...
  9. 30分钟用flex测试FDS
  10. 如何将txt中的数据整理到Matlab中画图
  11. 不定积分 基本积分表
  12. Qt 之 模仿 QQ登陆界面——样式篇
  13. win7上搭建ftp站点
  14. 汽车分类(奔驰G系列和奔驰c系列)
  15. 联通鸿蒙卡怎么样,联通不限流量卡,联通无限流量,正规资费
  16. NCRE公共基础知识(一) 计算机系统
  17. xenserver安装配置
  18. c语言输入一个三位数由小到大排序,c语言程序设计练习题.doc
  19. 46、W25Q128 存储器工作原理
  20. C语言,实现字符的渐变,动态化。

热门文章

  1. react进入路由前获取数据_react之传递数据的几种方式props传值、路由传值、状态提升、redux、context...
  2. windows下编译c语言文件路径,解决JNI在Windows环境下因长路径导致编译失败问题
  3. 什么叫内部银团_什么样的户型是好户型
  4. java怎么写网络爬虫_教你如何编写简单的网络爬虫
  5. javascript Exception handling statements(异常处理)
  6. msf监听php反弹shell,使用msf进行反弹shell+内网渗透
  7. python爬取网页内容_Python爬虫原理解析
  8. list 操作 java_Java,List操作技巧
  9. 在 vCenter Server 中触发了 vSphere Distributed Switch 绑定警报 (2057667)
  10. Exchange Server 2016 独立部署/共存部署 (一)—— 前期准备