模板的多态(静多态)威力
多态是一种能够令单一泛型标记关联不同特定行为的能力,对面向对象程序设计而言多态是一块基石。C++中通过继承和虚函数实现在运行期处理这种行为的能力,我们称为动多态。然而模板也允许我们使用这种单一泛型标记来关联不同的特定行为,这种关联是在编译期间进行处理的,我们称之为静多态。
一、概念
动多态:使用继承、虚函数,基类指针实现透明地处理不同类型集合的方法(运行时多态)
静多态:使用模板参数对不同类型集合实现透明地处理的方法(编译时期多态)
二、动多态:通过继承实现的多态是绑定和动态的。
绑定的含义是:对于参与多态行为的类型,他们(具有多态行为)的接口是在公共基类的设计中就预先确定了的(有时候也把这个绑定的概念称为入侵式或者插入式的)
动态的含义是:接口在运行期动态的被绑定
三、静多态:通过模板实现的多态是非绑定的和静态的
非绑定的含义是:对于参与多态行为的类型,他们是相互独立的,没有必要用基类将他们联系起来,也没有必要在基类中事先预定公共接口,只要在这个集合中大家约定好接口的名称就好了。(有的时候也称这个概念为非入侵式或者非插入式)
静态的含义是:接口在编译时期完成绑定。
【编者感悟】什么是入侵式什么是非入侵式?如果现在我们需要增加一个新的多态类型的接口,动多态就需要在基类中提供这一接口的声明(如果是纯函数,那么其子类也需要跟着一起修改添加声明和定义)甚至是定义,这就需要“入侵”到基类,修改基类的公共接口规范!如果是静多态,那我们就可以画出一个子集,只是在需要这一新的公共接口的类型的集合中添加这一接口的声明或者定义,而不必修改到其他未参与的类型的接口规范。
四、动多态优点
(1)能够优雅的处理一个包含有不同类型的集合。
(2)可执行代码量通常比较小(相比于模板实现的静多态,为了处理不同的类型,必须生成多个不同的模板实例)
(3)可以对代码进行完全编译;因此不需要发布源码(如果是分发模板库通常需要分发模板的源码)
五、静多态优点
(1)可以很容易的实现内建类型的集合。并不需要通过公共基类来表达接口的共同性
(2)所生成的代码效率会比较高(因为不存在通过指针的剪接引用,而且可以进行演绎的废墟你函数具有更多的内联机会)
(3)对于只提供了部分接口的具体类型,如果只是在程序中使用这一部分接口,那么也可以使用该具体类型,而不必在乎该具体类型是否提供了其他部分接口。(如果是动多态,基类的公共接口通常设计成纯虚函数,那么在子类的具体类中就需要全部实现这些函数的定义)
通常而言,静多态具有更好的类型安全性,因为静多态在编译期间会对所有的绑定做检查。
六、泛型程序设计
泛型程序设计师计算机科学的一个分支,他运用自身系统的组织,来找到高效的算法,数据结构和其他软件的概念的抽象表达,以及它们系统化的组织方式。泛型程序设计主要着重于表示一组相关领域概念。
泛型程序设计最著名的贡献就是STL(Standard Template Library)。STL实际是一个框架,它提供了很多游泳的操作,我们也把这些操作称之为是算法。他也为我们提供了很多线性的数据结构,我们把这些数据结构称之为容器。而且算法和容器都是模板。、
①算法不是容器的成员函数
②为了让容器使用这些算法
STL使用了一个叫做“迭代器”的概念。从本质上讲,容器针对集合方面的操作都被外包到迭代器功能上了。
template<class Iterator>
Iterator max_element(Iterator beg. Iterator end)
{
//使用迭代器来遍历集合的所有元素
}
namespace std{
template <class T, 。。。>
class vector{
public:
typedef ... const_iterator;
const_iterator begin() const;
const_iterator end() const;
};
termplate <class T,。。。>
class list{
public:
typedef ...const_iterator;
...
const_iterator begin() const;
const_iterator end() const;
};
}
#include <vector>
#include <list>
#include<algorithm>
#include <iostream>
template<typename T>
void print_max(T const& coll)
{
typename T::const_iterator pos;
pos = std::max_element(coll.begin(), coll.end());
if(pos != coll.end()){
std::cout << *pos << std::endl; //可见迭代器其实很像指针
}else{
std::cout << "empty" << std::endl;
}
}
int main()
{
std::vector<MyClass> c1;
std::vector<MyClass> c2;
print_max(c1);
print_max(c2);
return 0;
}
编辑整理:Claruarius,转载请注明出处。