野男人

不想做CEO的程序员不是一个好的产品经理

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  众所周知,C++STL实现了很多的算法,这些算法给程序员带来了很多的方便,一般情况下,如果你的项目没有特殊的要求,采用这些算法都比我们自己动手起来要简洁、高效。这些算法的成功,依赖的是大家耳熟能详的泛型思想。

你可能会说 “泛型编程”我很熟了,不就写几个模板?没错,泛型编程是应用模板技术做一些数据抽象的过程。但在享受着它给你带来便利的同时,你是否想过这背后的设计需求是什么吗?你是否想过为什么要这样去实现吗?可能你觉得不必要去深究这些东西,毕竟只要会如何使用它就好了。但是如果你知道了为何要这样设计的原因后,我想对你总是会有些好处的。

让我们看看一个List数据结构的实现,这里我并不是去剖析STLlist的实现代码。而是用C去实现类似的功能,我想暂时先让你“痛苦”一下,坐拖拉机走山路。然后再让你坐豪华汽车跑高速。


Code

这个定义模拟了面向对象中的数据与方法整合在一起,它实现存放任何类型指针的集合以及对集合上的操作。

首先我们看一下这样的定义有没有什么问题,注意看结构中出现了一个Sort方法,看起来需要实现对整个 List的数据进行排序。这里就涉及到一个问题,大家都知道排序有很多种类,比如:快速排序,冒泡排序,多关键字排序等。这些算法也各有特点,每个应用场景都不太一样。而现在把 Sort 功能与数据封装在一起,让程序库使用者如何选择想要的排序算法呢?针对每一种算法提供一个实现,封装进数据结构中,这样的话必须针对每一种数据类型都提供算法的实现,但是这样的话复用性不好,而且会产生很多重复代码。

为了不把问题搞的太复杂,也许你认为对算法的选择不那么重要,所以就选择任意一个能达到目的的算法,比如选择冒泡排序来实现,见下面的代码:


Code

请注意有注释的那段代码,Sort方法调用了一个叫 Equals方法。该方法也是由集合封装的。粗看起来没有什么问题,接着我们再看看Equals 方法的实现。

long ArrayList_Equals(const void *pValue1 , const void *pValue2)

{

    return strcmp(pValue1 , pValue2) ;

}

 

啊,看起来真的好简洁,直接调用了一个库函数 strcmp就完成了任务。我想学过C的程序员一看到 strcmp就很亲切。不过不要高兴的太早,让我们回到数据项的定义:void **Item ;这里的指针类型是 void,说明它可以存放任何数据类型。而刚才Equals 的实现却是用字符串的比较函数,也就是说这个list 只能存放字符类型的才能保证产生正确的结果。要是遇上里面存放的是INT或其它结构体类型的数据,那不就麻烦了。难道需要针对每一种数据类型都实现一个排序版本?按这样写出来的代码会非常臃肿,并且难于维护和使用。

       如果你的使用的语言支持泛型编程,那么这些问题就不用我们操心了。让我们回去看看在应用STL排序算法的时候是如何做到解决上面提到的两个问题的。

看一段 MSDN 的示例代码:


Code

这里没有列出STL的源码,但从sort方法的调用可以看出,STL 中把算法独立出来了。不局限于某种数据类型, 这样就解决了僵硬的缺点,让程序员可以自由的选择实际需要的算法。当然这些都依赖于编译器的支持,如果用C实现这样的功能,恐怕需要费一番周折了。

       接下来 sort( v1.begin( ), v1.end( ), UDgreater ); 看第三个参数,直接传了个函数指针。没有把功能做僵硬,而把“比较运算子”交由最终使用者去实现了,这样就达到了可扩展性、可伸缩性的目的。

 

相关文章阅读:

用C语言封装数据与方法 

posted on 2009-07-10 09:08  野男人  阅读(2734)  评论(7编辑  收藏  举报