a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 235|回复: 4

[程序员] 计算机软考程序员:C语言的多态实现

[复制链接]
发表于 2012-8-2 08:51:15 | 显示全部楼层 |阅读模式
相信很多人都看过设计模式方面的书,大家有什么体会呢?Bridge,Proxy,Factory这些设计模式都是基于抽象类的。使用抽象对象是这里的一个核心。    其实我觉得框架化编程的一个核心问题是抽象,用抽象的对象构建程序的主体框架,这是面向对象编程的普遍思想。用抽象构建骨架,再加上多态就形成了一个完整的程序。由于C++语言本身实现了继承和多态,使用这样的编程理念(理念啥意思?跟个风,嘿嘿)在C++中是十分普遍的现象,可以说Virtual(多态)是VC的灵魂。  `& D3 H3 t  J. N; \: ^
    但是,使用C语言的我们都快把这个多态忘光光了。我常听见前辈说,类?多态?我们用的是C,把这些忘了吧。很不幸的是,我是一个固执的人。这么好的东西,为啥不用呢。很高兴的,在最近的一些纯C代码中,我看见了C中的多态!下面且听我慢慢道来。+ p9 p. X9 A6 d4 ?
    1. VC中的Interface是什么
. ^) O) Y- ]8 Z8 e    Interface:中文解释是接口,其实它表示的是一个纯虚类。不过我所要说的是,在VC中的Interface其实就是struct,查找Interface的定义,你可以发现有这样的宏定义:
! F8 F5 X9 S$ J/ s8 n- u1 ]4 ^    #Ifndef Interface
: d' [* j. T, [/ j, D' [    #define Interface struct6 }2 ?6 j* M/ D! A, f( S6 J
    #endif% T5 ?1 B: V$ x8 C2 X4 `
    而且,实际上在VC中,如果一个类有Virtual的函数,则类里面会有vtable,它实际上是一个虚函数列表。实际上C++是从C发展而来的,它不过是在语言级别上支持了很多新功能,在C语言中,我们也可以使用这样的功能,前提是我们不得不自己实现。
回复

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:16 | 显示全部楼层

计算机软考程序员:C语言的多态实现

2.C中如何实现纯虚类(我称它为纯虚结构)    比较前面,相信大家已经豁然开朗了。使用struct组合函数指针就可以实现纯虚类。
5 b& i5 B; z( n& R    例子:
; u# f, X; y/ L3 C5 v6 ~    typedef struct {' F9 W( d4 T9 z/ g
      void (*Foo1)();
8 B" L" K* k; X4 e% G& o3 P9 {' Y      char (*Foo2)();
* E# [' h9 u- r! J1 y/ N+ D      char* (*Foo3)(char* st);
' y0 ^6 Y9 \1 d, _    }MyVirtualInterface;
, Y: m, p4 O9 n0 B# @+ _    这样假设我们在主体框架中要使用桥模式。(我们的主类是DoMyAct,接口具体实现类是Act1,Act2)下面我将依次介绍这些“类”。(C中的“类”在前面有说明,这里换了一个,是使用早期的数组的办法)
4 G. L( ^! w% G    主类DoMyAct: 主类中含有MyVirtualInterface* m_pInterface; 主类有下函数:
9 s8 s. Q/ w5 V/ ^3 X    DoMyAct_SetInterface(MyVirtualInterface* pInterface)
4 i1 |' w4 |% {    {
1 C& @, ^* e5 Y8 B. {! C) @7 n9 d8 @      m_pInterface= pInterface;
* S& w2 U  c. x, p    }3 d' z- e, K: x5 ]/ I
      DoMyAct_Do()
; B( ]# N0 t4 D5 H& x$ l    {
- R7 `* C$ n& P4 L0 X7 k      if(m_pInterface==NULL) return;
8 Q* a) W8 m+ n/ E) |        m_pInterface->Foo1();
, o0 f8 C" K/ g# l4 L' X        c=m_pInterface->Foo2();
2 E  U( e7 P2 Q' d8 P, X3 p    }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:17 | 显示全部楼层

计算机软考程序员:C语言的多态实现

子类Act1:实现虚结构,含有MyVirtualInterface st[MAX]; 有以下函数:    MyVirtualInterface* Act1_CreatInterface()
4 C+ {0 T5 \$ T( Z; o    {
4 D$ [. H. [3 {6 G      index=FindValid()
* I! s& a4 F. e* y' s1 |      //对象池或者使用Malloc !应该留在外面申请,实例化% b/ d! }' m2 B* w3 c/ T; _
      if(index==-1) return NULL;
# S% u( ]/ F" ~3 {5 p1 u" u8 [4 d      St[index].Foo1=Act1_Foo1; 5 }' b: u8 B9 K6 v' m5 c
      // Act1_Foo1要在下面具体实现3 X; Y$ y, B: w& a: E5 j
      St[index].Foo2=Act1_Foo2;
8 n! j! W0 |# U# D8 N- {" ~: x      St[index].Foo3=Act1_Foo3;
# Y4 }5 L( e. n2 @  j      Return &st [index];4 _" e% b* q' C. X
    }
0 v5 H# y) X; u. i; z1 _2 W, M    子类Act2同上。$ _1 w. u) Y7 K; ]8 ^  `" V  {
    在main中,假设有一个对象List。List中存贮的是MyVirtualInterface指针,则有:+ _7 Z3 I3 y; k' g: [  x
    if((p= Act1_CreatInterface()) != NULL)- d9 @- \) Z8 x& P. V4 t) T
      List_AddObject(&List, p); //Add All& _; O* L; `; Y8 B: }% J$ T
    While(p=List_GetObject()){5 L2 {) p6 b1 _
      DoMyAct_SetInterface(p);//使用Interface代替了原来大篇幅的Switch Case7 W1 [7 X# D. I8 M. b
      DoMyAct_Do();//不要理会具体的什么样的动作,just do it; ~/ r' V" Q+ p, t* K8 F+ f
    }
$ w5 M+ h/ y0 ^/ _$ I    FREE ALL。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:18 | 显示全部楼层

计算机软考程序员:C语言的多态实现

在微系统里面,比如嵌入式,通常使用对象池的技术,这个时候可以不用考虑释放的问题(对象池预先没有空间,使用Attach,在某个函数中申请一个数组并临时为对象池分配空间,这样函数结束,对象池就释放了)    但是在Pc环境下,由于程序规模比较大,更重要的是一些特殊的要求,使得对象的生命周期必须延续到申请的那个函数体以外,就不得不使用malloc,实际上即使在C++中,new对象的自动释放始终是一个令人头疼的问题,新的标准引入了智能指针。但是就我个人而言,我觉得将内存释放的问题完全的交给机器是不可信任的,它只能达到准最佳。4 x( ]' _* F( h! N8 Y. P
    你知道设计Java的垃圾回收算法有多困难吗?现实世界是错综复杂的,在没有先验条件下,要想得到精确的结果及其困难。所以我说程序员要时刻将free记在心上,有关程序的健壮性和自我防御将在另外一篇文章中讲述。
. `" k7 t$ l" s( c' d5 P8 [* L* f- ~    3.纯虚结构的退化
9 B1 F2 x  b3 s& C: I7 B    下面我们来看看如果struct里面仅仅有一个函数是什么? 这个时候如果我们不使用struct,仅仅使用函数指针又是什么? 我们发现,这样就退化为普通的函数指针的使用了。/ q- Q2 i. R9 \( p' B; a
    所以说,有的时候我觉得面向对象仅仅是一种形式,而不是一种技术。是一种观点,而不是一种算法。但是,正如炭,石墨和钻石的关系一样,虽然分子式都是C,但是组成方法不一样,表现就完全不一样了!
6 m& `, h6 a  k8 [7 y; U    有的时候,我们经常被编程中琐碎的事情所烦恼,而偏离了重心,其实程序可进化的特性是很重要的。有可能,第一次是不成功的,但是只要可进化,就可以发展。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-2 08:51:19 | 显示全部楼层

计算机软考程序员:C语言的多态实现

4.进阶――类结构树,父类不是纯虚类的类    前面仅仅讲的是父类是纯虚结构的情况 (面向对象建议的是所有类的基类都是从纯虚类开始的), 那么当类层次比较多的情况下,出现父类不是纯虚结构怎么办呢。嘿嘿,其实在C中的实现比C++要简单多了。因为C中各个函数是分散的。2 ]2 l3 h$ i- M5 U+ ^2 d
    在这里使用宏定义是一个很好的办法:比如两个类Act1,ActByOther1“继承”Act1:
; N& H/ E/ H; c* J2 H7 S1 C    MyVirtualInterface* ActByOther1_CreatInterface()0 s$ C3 n' l$ F7 e
    {
3 L: P/ T+ V: F6 A: J1 U6 Q! [      index=FindValid()) n5 v- L3 Z1 z8 d& v+ f. |
      //对象池或者使用Malloc
! m1 r) ~& T1 p. l) _      if(index==-1) return NULL;
: w/ P5 z& H- K1 `  o  Q" A. T- [      St[index].Foo1= ActByOther1_Foo1;! ?5 c; b( r# @3 L
      // Act1_Foo1要在下面具体实现
) \3 y3 ~  l% N' _8 ~      St[index].Foo2= ActByOther1_Foo2;
/ A7 B' i" V" V! b' M; o2 N# G      St[index].Foo3= ActByOther1_Foo3;8 |8 o7 ~: z8 m3 a) d: M1 r
      Return &st [index];0 ^% v- W/ R- Y9 L: o( B
    }4 [* F1 ~& H/ C3 g  N) q6 l+ |
    #define ActByOther1_Foo1 Act1_Foo1 //这就是继承 嘿嘿
" x+ M& \  U7 Q. T& g7 |# `, |      ActByOther1_Foo2(){} // 可以修改其实现3 H$ K5 L' j* r: S; [5 ]
      ActByOther1_DoByOther() {} //当然就可以添加新的实现咯
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-18 09:53 , Processed in 0.182313 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表