C++代码重构——从C global到C++ template
在学数据结构的时候。我常有这样目标——写出可以最大程度复用的代码(算法正确,封装优秀)。我常想——怎样能在短时间内达成“算法正确,封装优秀”这种目标。
经过一段时间的摸索,我的结论是:先用C写出正确的算法,再将它改写成C++ class,最后再考虑改为template。这个方案简单可行。基本实现了 逻辑(算法)设计与接口设计两个步骤的分离。
在写数据结构代码的场景下,使用这样的方法的前提是——你必须先把这个数据结构须要哪些操作弄清楚。而且有怎样实现的大致思路(假设不清楚,翻翻书☺)。
以下以一个有界队列为例。进行演示。
正确的算法
在考虑怎样实现算法时。能够全然不用不论什么封装(C struct的封装也不用),仅仅要实现最小操作集合即可了,但測试必需要写。
这里就是实现所谓的“环形缓冲”。空出一个用于区分队满和队空。连同測试,代码例如以下:
(执行结果不在此贴出。感兴趣的同学自己执行)
在仅仅考虑算法不考虑接口的情况下。写出这种代码非常easy(相信有点语言功底的都能写得出来)。当然,上面的#define TEST能够不写。用编译选项定义也是能够的。
封装为class
有了这种基础,封装为C++ class就非常easy了(这里直接包裹,实际情形可能有功能类似但參数不同的接口,略作封装就可以)。这么简单的成员函数,没有必要分开来了。这里就用一个.h:
封装为类之后,測试代码有必要分开来写:
封装为类之后,測试代码有必要分开来写:
重构为class template
显然,这样直接封装的有界队列存在问题——元素类型固定(这一般是写成template的理由)。缓冲大小固定。对于第一点。能够通过将代码重构为C++的类模板实现;即将元素的类型作为类模板的一个參数。对于第二点,也能够借助模板參数实现(模板除了有类型參数,也能够有值參数)。当然也能够把buffer改为指针。在ctor传入大小。这里不做介绍。代码例如以下:
此时的測试代码:
这里描写叙述的方法(C->OO->template)主要是从代码复用的角度考虑,并不是与传统OOP教材上的“先接口后实现”相违背。你能够理解为——怎样让《数据结构》教材上的C代码的到最大程度上的复用。
(多数《数据》教材採用C代码解说,当然也有使用其它语言的)
直接使用“先接口,后实现”的方法,并不是不行。仅仅是可能要多改非常多次代码(尤其是考虑模板的时候T^T,想想都是泪。不能让学弟学妹们掉相同的坑了)。使用本文所述方法的优点就是——能够让逻辑设计与接口设计两个过程解耦。