泛型编程

一、泛型

泛型编程最初诞生于C++中,目的是为了实现C++的STL(标准模板库)。其语言支持机制就是模板(Templates)。模板的精神其实很简单:参数化类型。换句话说,把一个原本特定于某个类型的算法或类当中的类型信息抽掉,抽出来做成模板参数T。

泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象,这样的事情;熟悉一些其它面向对象的语言的人应该知道,如Java里面这是通过在List里面存放Object引用来实现的。Java的单根继承在这里起到了关键的作用。然而单根继承对C++这样的处在语言链底层的语言却是不能承受之重。此外使用单根继承来实现通用容器也会带来效率和类型安全方面的问题,两者都与C++的理念不相吻合。

于是C++另谋他法——除了单根继承之外,另一个实现通用容器的方案就是使用“参数化类型”。一个容器需要能够存放任何类型的对象,那干脆就把这个对象的类型“抽”出来,参数化它:

template<class T> class vector
{
    T* v;
    int sz;
public:
    vector(int);
    T& operator[](int);
    T& elem(int i) { return v[i]; }
// ...
};

一般来说看到这个定义的时候,每个人都会想到C的宏。的确,模板和宏在精神上的确有相仿之处。而且的确,也有人使用C的宏来实现通用容器。模板是将一个定义里面的类型参数化出来,而宏也可以做到参数化类型。甚至某种意义上可以说宏是模板的超集——因为宏不仅可以参数化类型,宏实质上可以参数化一切文本,因为它本来就是一个文本替换工具。然而,跟模板相比,宏的最大的缺点就是它并不工作在C++的语法解析层面,宏是由预处理器来处理的,而在预处理器的眼里没有C++,只有一堆文本,因此C++的类型检查根本不起作用。比如上面的定义如果用宏来实现,那么就算你传进去的T不是一个类型,预处理器也不会报错;只有等到文本替换完了,到C++编译器工作的时候才会发现一堆莫名其妙的类型错误,但那个时候错误就已经到处都是了。往往最后会抛出一堆吓人的编译错误。更何况宏基本无法调试。

二、有面向对象为什么还需要GP?

谈泛型(GP)之前, 先谈一下面向对象(OO), OO强调世界是由对象组成的,对象是由方法和属
性组成的(个人感觉还应该加上事件),而对象之间又有继承(is-a)和组合等 关系。OO很符合
我们认识世界的直觉,它以封装,继承和多态为特性,我们在现实工作中又总结出来了OO的5大
设计原则和23种设计模式。总之,OO基本上已经可以很好的解决我们现实生活中的所有问题。

那么既然OO已经可以很好的解决我们的问题了,为什么还要有GP? 

我们先来看一下OO的缺点:
OO的多态是通过继承自同一接口来实现的, 修改接口会导致所有派生类的修改,耦合比较紧
密。
OO的多态是运行时的, 性能比较低。
OO的多态通过抽象接口实现,使用不安全,在不支持反射的语言(比如C++)中会丧失类型检测。 

用OO设计时,你只能通过抽象接口来处理不同的事物。比如你要让Cat和Dog同时跑动,你可能
会抽象出一个IAnimal接口,内部有一个Run的方法,然后让Cat和Dog分别继承。但是如果你
想让猫(Cat)和玩具猫(ToyCat)支持跑动,这时你抽象出IAnimal就不合适了, 你可能会抽
象出ICatProperty。可以看到OO的这种继承体系非常笨重,到后面可能会导致非常深的继承
层次(比如MFC),代码扩展和维护都很艰难。

上面OO的这些缺点在GP没有被发现之前都不是缺点,因为我们没有更好的解决方案,但是人们逐
渐发现了GP,GP最初是在使用容器(Container)时被发现的,container<T>可以放任意类
型的元素,根据元素类型,我们可以可以生成任意类型的container. 这些技术后来发展成泛
型编程和模板元编程。

C++泛型的另一个好处就是,跟面向对象编程的基于继承和虚函数的运行时多态机制不同,C++模板是非侵入性的。你不需要让你的类继承自某个特定的接口才能用于某个算法,只要支持特定的语法接口就行了(比如只要支持begin()调用)。这也被称为结构一致性(Structural Conformance),意即只要语法结构一致即可。而另一方面,基于接口继承的面向对象多态则必须要显式地声明继承自一个接口,这就是所谓的名字一致性(Named Conformance)。

当然,泛型支持的静态多态和虚函数支持的动态多态并没有任何程度上绝对的优劣之分。它们适用于不同的场合。当类型信息可得的时候,利用编译期多态能够获得最大的效率和灵活性。当具体的类型信息不可得,就必须诉诸运行期多态了。

http://blog.youkuaiyun.com/pongba/article/details/2544894
http://www.cppblog.com/weiym/archive/2012/11/10/195012.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值