泛型编程拾遗

时间:2021-07-11 19:26:36

  首先请大家思考一个问题:以下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思想》