为什么80%的码农都做不了架构师?>>>   

转自:http://hi.baidu.com/todaygoodhujun/blog/item/7b3b7cecf4c716d12f2e2132.html

C语言的多态实现
       相信很多人都看过设计模式方面的书,大家有什么体会呢?Bridge,Proxy,Factory这些设计模式都是基于抽象类的。使用抽象对象是这里的一个核心。
      
       其实我觉得框架化编程的一个核心问题是抽象,用抽象的对象构建程序的主体框架,这是面向对象编程的普遍思想。用抽象构建骨架,再加上多态就形成了一个完整 的程序。由于C++语言本身实现了继承和多态,使用这样的编程理念(理念啥意思?跟个风,嘿嘿)在C++中是十分普遍的现象,可以说Virtual(多 态)是VC的灵魂。
 
       但是,使用C语言的我们都快把这个多态忘光光了。我常听见前辈说,类?多态?我们用的是C,把这些忘了吧。很不幸的是,我是一个固执的人。这么好的东西,为啥不用呢。很高兴的,在最近的一些纯C代码中,我看见了C中的多态!下面且听我慢慢道来。
 
1. VC中的Interface是什么
       Interface:中文解释是接口,其实它表示的是一个纯虚类。不过我所要说的是,在VC中的Interface其实就是struct,查找Interface的定义,你可以发现有这样的宏定义:
       #Ifndef Interface
              #define Interface struct
       #endif
而且,实际上在VC中,如果一个类有Virtual的函数,则类里面会有vtable,它实际上是一个虚函数列表。实际上C++是从C发展而来的,它不过是在语言级别上支持了很多新功能,在C语言中,我们也可以使用这样的功能,前提是我们不得不自己实现。
 
2.C中如何实现纯虚类(我称它为纯虚结构)
       比较前面,相信大家已经豁然开朗了。使用struct组合函数指针就可以实现纯虚类。
例子: typedef struct {
                     void  (*Foo1)();
                     char  (*Foo2)();
                     char*  (*Foo3)(char* st);
              }MyVirtualInterface;
      
       这样假设我们在主体框架中要使用桥模式。(我们的主类是DoMyAct,接口具体实现类是Act1,Act2)下面我将依次介绍这些“类”。(C中的“类”在前面有说明,这里换了一个,是使用早期的数组的办法)
 
主类DoMyAct: 主类中含有MyVirtualInterface* m_pInterface; 主类有下函数:
                            DoMyAct_SetInterface(MyVirtualInterface* pInterface)
                            {
                                   m_pInterface= pInterface;
                            }
                            DoMyAct_Do()
                            {
                                   if(m_pInterface==NULL) return;
                                   m_pInterface->Foo1();
                                   c=m_pInterface->Foo2();
                            }
子类Act1:实现虚结构,含有MyVirtualInterface  st[MAX]; 有以下函数:
                    MyVirtualInterface* Act1_CreatInterface()
                     {
                            index=FindValid() //对象池或者使用Malloc !应该留在外面申请,实例化
                            if(index==-1) return NULL;
                            St[index].Foo1=Act1_Foo1; // Act1_Foo1要在下面具体实现
                            St[index].Foo2=Act1_Foo2;
                            St[index].Foo3=Act1_Foo3;
                            Return &st [index];
                     }
子类Act2同上。
 
在main中,假设有一个对象List。List中存贮的是MyVirtualInterface指针,则有:
       if( (p= Act1_CreatInterface()) != NULL)
       List_AddObject(&List, p); //Add All
 
       While(p=List_GetObject()){
              DoMyAct_SetInterface(p);//使用Interface代替了原来大篇幅的Switch Case
              DoMyAct_Do();//不要理会具体的什么样的动作,just do it
       }
 
       FREE ALL。
       在微系统里面,比如嵌入式,通常使用对象池的技术,这个时候可以不用考虑释放的问题(对象池预先没有空间,使用Attach,在某个函数中申请一个数组并临时为对象池分配空间,这样函数结束,对象池就释放了)
 
       但是在Pc环境下,由于程序规模比较大,更重要的是一些特殊的要求,使得对象的生命周期必须延续到申请的那个函数体以外,就不得不使用malloc,实际 上即使在C++中,new对象的自动释放始终是一个令人头疼的问题,新的标准引入了智能指针。但是就我个人而言,我觉得将内存释放的问题完全的交给机器是 不可信任的,它只能达到准最佳。
 
       你知道设计Java的垃圾回收算法有多困难吗?现实世界是错综复杂的,在没有先验条件下,要想得到精确的结果及其困难。所以我说程序员要时刻将free记在心上,有关程序的健壮性和自我防御将在另外一篇文章中讲述。
 
3.纯虚结构的退化
       下面我们来看看如果struct里面仅仅有一个函数是什么? 这个时候如果我们不使用struct,仅仅使用函数指针又是什么? 我们发现,这样就退化为普通的函数指针的使用了。
 
       所以说,有的时候我觉得面向对象仅仅是一种形式,而不是一种技术。是一种观点,而不是一种算法。但是,正如炭,石墨和钻石的关系一样,虽然分子式都是C,但是组成方法不一样,表现就完全不一样了!
       有的时候,我们经常被编程中琐碎的事情所烦恼,而偏离了重心,其实程序可进化的特性是很重要的。有可能,第一次是不成功的,但是只要可进化,就可以发展。
 
4.进阶――类结构树,父类不是纯虚类的类
       前面仅仅讲的是父类是纯虚结构的情况 (面向对象建议的是所有类的基类都是从纯虚类开始的), 那么当类层次比较多的情况下,出现父类不是纯虚结构怎么办呢。嘿嘿,其实在C中的实现比C++要简单多了。因为C中各个函数是分散的。
 
在这里使用宏定义是一个很好的办法:比如两个类Act1,ActByOther1“继承”Act1:
                    MyVirtualInterface* ActByOther1_CreatInterface()
                     {
                            index=FindValid() //对象池或者使用Malloc
                            if(index==-1) return NULL;
                            St[index].Foo1= ActByOther1_Foo1; // Act1_Foo1要在下面具体实现
                            St[index].Foo2= ActByOther1_Foo2;
                            St[index].Foo3= ActByOther1_Foo3;
                            Return &st [index];
                     }
 
       #define ActByOther1_Foo1 Act1_Foo1  //这就是继承 嘿嘿
       ActByOther1_Foo2(){}                    //  可以修改其实现
    ActByOther1_DoByOther() {}         //当然就可以添加新的实现咯
 
5.实例――可以参见H264的源码,其中NalTool就是这样的一个纯虚结构。

转载于:https://my.oschina.net/dake/blog/196720

C语言中的面向对象2相关推荐

  1. php语言中的符号,php语言中的面向对象

    php语言中的面向对象 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物.下面小编要给大家讲述的是php语言中的面向对象,欢迎阅读,更多详情请关注应届毕业生考试网. p ...

  2. c加加属于面向对象的程序设计语言吗,下列语言中属于面向对象的程序设计语言是______。A、Visual BasicB、PASCALC、CD、FORTRAN...

    下列语言中属于面向对象的程序设计语言是______.A.Visual BasicB.PASCALC.CD.FORTRAN 更多相关问题 经纬仪如存在指标差,将使观测结果出现( ). 德治的约束作用主要 ...

  3. 如何利用函数指针在c语言中实现面向对象编程

    面向过程编程 c语言,是一种函数流语言,看他的代码,大部分是call1(data), call2(data)类似的代码.所以他的主体思想是函数,把数据丢进去给函数执行. 面向对象编程 java语言,和 ...

  4. c语言里的%p的作用,c语言中 %p的含义

    格式控制符"%p"中的p是pointer(指针)的缩写.指针的值是语言实现(编译程序)相关的,但几乎所有实现中,指针的值都是一个表示地址空间中某个存储器单元的整数.printf函数 ...

  5. Cocos2d-x 脚本语言Lua中的面向对象

    Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类 ...

  6. 面向对象的C语言编程-DynamicLinkageGenericFunctions--C语言中的偷梁换柱

    文章目录 `DynamicLinkageGenericFunctions` Constructors and Destructors 方法.信息.类和对象 `new` `delete` `clone` ...

  7. c语言中如何使用面向对象编程,如何使用C语言的面向对象

    我们都知道,C++才是面向对象的语言,但是C语言是否能使用面向对象的功能? (1)继承性 typedef struct _parent { int data_parent; }Parent; type ...

  8. C语言中面向对象编程

    C语言中面相对象的编程 面向对象的重要思想就是数据隐藏,在面向对象语言中,对象可以包含私有变量.这样我们可以说他们具有内部状态,这些内部状态对其他对象是透明的.全局变量可以通过设置变量作用域来模拟私有 ...

  9. C语言中面向对象的尝试

    C语言中面向对象的尝试 作者:周志明 说明:程序中关于画直线和园的算法,请参阅图形学相关知识.算法部分写在在main函数后. 运行环境:TC2.0(运行时候注意路径问题) #include<gr ...

最新文章

  1. 49 款人脸检测/识别的API、库和软件
  2. react connect
  3. Apache Qpid 认证绕过漏洞
  4. 嵌入式操作系统内核原理和开发(总结篇)
  5. JS小项目 ----- 可视化冒泡排序
  6. python request microsoft graph_Microsoft Graph API:授权未找到
  7. 自己整理出来的一些标签
  8. python照片过人脸_python图片人脸检测
  9. 机器学习中强化学习的一些知识
  10. 可以使用python开发财务软件吗_给还准备继续做审计的人提个醒!
  11. 获取USB摄像头名字和device ID等信息
  12. 个人博客系统项目-已开源
  13. Java学习系列之抽象类和接口的区别和联系
  14. iOS开发中常用的方法
  15. C++实现内存“垃圾”回收机制
  16. 三星android one 拍照功能,三星One UI 3.1体验:更好用了,也更注重隐私了
  17. 《简明数学分析》郇中丹——1.2对课程学习的忠告
  18. 比亚迪没有奇迹:一个奶不大的孩子,一个走向平凡的车企
  19. 2023健康展/山东睡眠健康展/养生保健展/产后恢复与健康展
  20. 要想提高工作效率,请拒绝做这 7 种事

热门文章

  1. [转载] Pytorch入门实战-----逻辑回归识别手写数据集
  2. linux 用shell比较两个整数的大小
  3. 记录一些关于操作数据库(本地和linux服务器)常用的命令
  4. 十进制数转N进制c++实现
  5. SqlServer发布订阅错误收集
  6. 获取字符串全排列 或者 只输出k个的组合
  7. bzoj1079 [SCOI2008]着色方案
  8. 设计模式——“signleton”
  9. [转]C#正则表达式小结
  10. arduino upload程序时 出现can't open device /dev/ttyUSB0