Bootstrap

模板技术(编译多态)

运行时多态通过虚函数及虚表实现。
编译时多态通过模板、特化实现,通过为不同参数构建不同的类特化,实现编译时多态。

模板相关,特化,部分特化:

//主类模板
template<typename T>
class Stack {
private:
       std::vector<T> elems;
};
//完全特化
template<>
class Stack<std::string> {
private:
       std::deque<T> elems;
};
//部分特化
template<typename T>
class Stack<T*> {
private:
       std::list<T> elems;
};

总之,当模板参数满足一些特殊条件时,我们使用特化类模板来进行实例化。对于其他一般情形,仍然使用主类模板进行实例化。

Traits技术
使用traits技术,不同数据类型的特征被封装在一个类模板中,通过模板特化技术,程序其他模块可以使用这个类模板的统一接口,获得每个数据类型的特征信息。
如下图:
定义一个主模板类;
特化两个类:float、double,在特化类中定义了相同的接口fp_type和epsilon()。
matrix类就可以通过上述类模板获取类型参数numT的相关信息(传入不同的参数,调用相同的接口,获取不同的值,这就是编译时多态)。
在这里插入图片描述
类型分类(Type Classification)
C++语言只有很少几个运算符能够处理“类型”:sizeof、dynamic_cast以及typeid
运算符sizeof只能够求取一个类型的对象所占用的内存空间。
对于含有虚函数的类,dynamic_cast可被用来判断一个对象是否具有某个类型,但是这个运算符只能施加到一个指针(或引用),不能施加到一个类型。
运算符typeid倒是适用于所有类型(或者这些类型的对象),但是它只能获得一个类型的名字信息。

既然C++本身不能够提供足够详细的信息,我们可以使用类模板特化技术(和traites技术很像),设计专门的类模板来提供所需信息,这种方法被称为类型分类(type classification)技术。
在这里插入图片描述
代码膨胀
每当一个模板被实例化一次,模板的代码就会被重复一次,导致程序代码段的增加,这个现象被称为代码膨胀(code bloat)。

为了降低代码膨胀,我们可以将一个类模板中与模板参数无关的代码隔离出来,形成一个确定的类(而非类模板),并令其成为基类,使该类模板实例化生成的类能够共享该基类的代码。(编译时多态)

如下设计一个vector类,Vector中可以存放指针类型的元素和非指针类型的元素。对这两种类型的元素有着不同的处理方法。设我们要为Vector新增一个成员函数insert(),该函数能够在容器某个位置插入一个元素,其后元素被依次后移,最后一个元素被移出丢弃。如果元素类型为指针,我们可以使用标准函数memcpy()来快速地完成这个后移操作。如果元素类型为非指针,就必须调用适用于该类型的赋值运算符,逐个后移。
在这里插入图片描述
针对指针类型,我们构造基类VPVector。然后对指针类型进行特化。
如此,则调用③、④的代码,则基类代码复用,避免代码膨胀。
在这里插入图片描述

;