泛型编程拾遗
首先请大家思考一个问题:以下6个问题可否共享一段代码?
答案是肯定的。采用泛型编程对问题进行抽象,抽取出以上问题的共性即算法(algorithm)、容器(container)和迭代器(itera),这也是STL(Standard Template Library, 标准模板库)的三要素。
1 template <class Iterator, class Act, class Test>
2
3 void process(Iterator begin, Iterator end, Act act, Test test)
4
5 //对容器中在给定范围内(即起于begin止于end)所有满足给定条件的元素进行处理
6
7 {
8
9 for (; begin != end; ++begin) //从头至尾遍历容器内的元素
10
11 if (test(*begin)) act(*begin); //若当前元素满足条件,则对其采取行动
12
13 }
其中,算法是一系列切实有效的步骤(Act/Test);容器是数据的集合,可以理解为抽象的数组(6个问题中需要遍历的数据集合);迭代器是算法与容器之间的接口,可理解为抽象的指针或游标(迭代器用以访问容器内元素,C++中指针就是一种迭代器)。以上程序中看不到元素的数据类型T,甚至也看不到存放数据的容器container,这是因为元素已经被容器封装,而容器通过迭代器参与算法。
这么说可能大家不是很理解,下面以第6个问题为例,展示泛型编程的魅力:
1 //Generic Programming 范型编程 by acelit http://www.cnblogs.com/always-chang/
2 #include <iostream>
3 #include <iterator>
4 using namespace std;
5
6 template <class Iterator, class Act, class Test>
7 void process(Iterator begin, Iterator end, Act act, Test test)
8 //对容器中在给定范围内(即起于begin止于end)所有满足给定条件的元素进行处理
9 {
10 for (; begin != end; ++begin) //从头至尾遍历容器内的元素
11 if (test(*begin)) act(*begin); //若当前元素满足条件,则对其采取行动
12 }
13 //判断是否为非数字字符
14 bool notDigit(char c)
15 {
16 return (c < '0') || (c > '9');
17 }
18 //打印非数字字符
19 void printNondigit(char c)
20 {
21 cout << c << "不是数字字符" << endl;
22 }
23
24 int main()
25 {
26 process(istream_iterator<char>(cin), istream_iterator<char>(), printNondigit, notDigit);
27
28 return 0;
29 }
问题6中的标准输入也是容器的一种,容器内元素类型为char,template <class Iterator, class Act, class Test>通过模板泛化了容器(还有数组、列表、集合、映射、队列、栈、字符串等),也泛化了元素(可以是任何数据类型),甚至泛化了处理方法和限定条件(迭代器本身就是一种检查容器内元素并遍历元素的数据类型,这种数据类型包含一组确定的操作来遍历、访问容器内的元素,当然遍历方法有很多种了,比如从前往后、从后往前、随机移动…)。
【泛化这个词可以理解为‘隐藏’,这里模板内仅有迭代器的声明,但是迭代器的类型是通过容器来定义的。】
istream_iterator<char>表示元素为char类型的标准输入流(容器)迭代器,()内有标准输入流对象cin表示容器开始位置,为空表示容器结束位置。
怎么样?泛型编程是不是使代码异常简洁,当然付出的代价是理解起来比较抽象了,这里完全看不到I/O读取的过程,也看不到通常的迭代循环,使我们完全摆脱了底层编码的细节,在更高、更抽象的层次上进行编程。
抽象和泛化使代码简洁高效、可重用性大大提高,是泛型编程的“屠龙之技”,也是我们必须掌握的编程技能。
欢迎讨论交流O(∩_∩)O
istream_iterator详见:
http://www.cplusplus.com/reference/iterator/istream_iterator/
更多迭代器和容器参考:
http://www.360doc.com/content/12/1128/13/9290626_250737796.shtml
本文参考:《冒号课堂——编程范式与OOP思想》