Effective c++ 第7章 模板与泛型编程

        模板与泛型程序可以创造出“在C++编译器内执行并于编译器完成时停止执行”的程序。


条款41:了解隐式接口与编译器多态

        classes和templates都支持接口和多态。

       对classes而言是显示的,以函数签名为中心。多台则是通过virtual函数发生于运行期。

       对template参数而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析发生于编译期。

        以不同的template具现化function templates会导致调用不同的函数,这就是编译期多态。运行期多态是指哪一个virtual被绑定,编译期多态是指哪一个重载还是会被调用。


条款42:了解typename的双重意义

        声明template参数时,前缀关键字class和typename可互换。

        请使用关键字typename标识嵌套从属类型名称,但不得在base classes lists(基类列表)或member initialization list(成员初始化列表)内使用它作为base class的修饰符。

        template内出现的名称如果相依于某个template参数,称之为嵌套从属名称。如果从属名称在类内呈嵌套状。称它为嵌套从属名称。如以下:

//嵌套从属类型
template <typename C>
print2nd(const C& container)
{
	//以下是一个嵌套从属名称,因为C是模板参数,并且const_iterator被嵌套于
	//这个C中,所以下面需要使用typename,表明它是一个类型
	typename C::const_iterator* x;
}
         之所以要加是因为C++解析这个有歧义的状态的规则是:如果解析器在template遭遇一个嵌套从属名称,它便假设这名称不是一个类型,除非你告诉他是。即缺省情况下嵌套从属名称不是类型。所以任何使用要在template中指涉一个嵌套从属类型名需要在它前面加typename,而且typename只能用来验明嵌套从属名称,正常类型不应该有他存在,如:

//typename只被用来验明嵌套从属类型名称,其他名称不该有它存在
template <typename C>   //允许使用typename与class,此中情况下等同
void f(const C& container,  //正常类型,不允许使用typename
		typename C::iterator iter);  //嵌套类型,需要使用typename

以上这个例外出现在以下这种情况,继承基类成员列表内的嵌套从属类型或在成员初始化列表中作为积累的修饰符,如下:

template <typename T>
class Derived : public Base<T>::Nested //基类列表中不允许
{
public:
	explicit Derived(int x)
		: Base<T>::Nested(x)   //成员初始化列表中不允许
	{
		typename Base<T>::Nested temp;  //嵌套从属类型加typename
	}
};

          最后一个typename的例子,是STL库中的typename的这种运用:

//STL中typename
template <typename IterT>
void workWithIterator(IterT iter)
{
	typename std::iterator_traits<IterT>::value_type temp(*iter);
}

          std::iterator_traits<IterT>::value_type是标准traits class的一种运用,意思就是说“类型为IterT之对象所指之物的类型”。语句的意思就是声明一个local变量,使用IterT对象所指物。如果IterT是vector<int>::iterator, temp的类型就是int, 如果是list<string>::iterator,temp类型就是string,以上是个嵌套从属类型,value_type嵌套于iterator_traits<IterT>之内而IterT是个template参数,所以前面必须加typename., 但这种类型太长,使用不方便,可以使用typedef声明一个类型,如下:

template <typename IterT>
void workWithIterator(IterT iter)
{
	//为嵌套从属类型使用一个类型声明符,value_type就代表这个类型
	typedef typename std::iterator_traits<IterT>::value_type value_type;
	value_type temp(*iter);
}

条款43:学习处理模板化基类内的名称

        如果一个类继承自一个模板类,则如果在继承类中直接调用基类的共有函数会失败,因为C++知道基类模板有可能被特化,而那个特化的版本可能不提供和一般性template相同的接口,所以它采取的行为是拒绝在templatized base classes(模板化基类)内寻找继承而来的名称。这与OO C++是不同的。为了使继承类进入模板基类内查找名称,有三种方式:

          1 在调用函数前使用this->func()   

          2 使用using声明式,这并不是base class名称被derived  class名称遮掩,而是编译器不进去查找,用using告诉他,然后它会进去超找。

          3 明确指出被调用的函数位于base class内,如MsgSender<Company>::sendClear(info),但这种情况如果被调用的是virtual函数,则这种调用方式会关闭”virtual绑定行为“。


条款44:将参数无关的代码抽离template

        Templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系

        因非类型模板参数而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数。

        因类型参数而造成的代码膨胀,往往可以降低,做法是让带有完全相同的二进制表述的具体类型共享实现码。


条款45:运用成员函数模板接受所有兼容类型

       请使用member function template生成“可接受所有兼容类型”的函数

        如果你声明member template用于“泛化copy构造”或"泛化assignment操作",你还是需要声明正常的copy构造函数和copy assignment操作符。

        真实指针支持隐式转换,Derived类指针可以隐式转换为基类指针,指向non-const对象的指针可以转换为“指向const对象“等等。


条款46:需要类型转换时请为模板定义非成员函数

       template实参推导过程中并不考虑采纳“通过构造函数而发生的”隐式类型转换。Class templates不依赖template实参推导(只施行于function templates身上),所以编译器能够在class Rational<T>具现化时得知T。
         在一个class template内,template名称可被用过来作为“template和其参数”的简略表达方式。所以Rational<T>可以只写Rational而不必写Rational<T>。
         当我们编写一个class template,而它所提供之“与此template相关的”函数支持“所有参数之隐式类型转换”时,请将那些函数定义为“class template内部的friend”函数。
         为了让类型转换可能发生于所有实参身上,需要一个non-member函数;为了令这个函数被自动具现化,需要将它声明在class内部;而在class内部声明non-member函数的唯一办法就是:令它成为一个friend。这个friend函数的定义要在类内部定义,当这个类太大时,可以令friend函数调用类外的辅助函数。


条款48:认识template元编程。
        Template metaprogramming(TMP)模板元编程:是以C++写成,执行于C++编译器内的程序。一旦TMP程序结束,其输出,也就是从templates具现出来的若干C++源码,便会一如既往的被编译。
        TMP:1让事情更简单 2 由于templatemetaprograms执行于C++编译期,也就是可以将工作从运行期转移到编译期。
         TMP已经被证明是“图灵完全的”机器,意思是威力大到足以计算任何事物。即可以声明变了,执行循环,编写及调用函数。TMP中的循环式藉由递归完成的。TMP是"函数式语言"。每个Factorial template具体现都是一个struct,每个struct都使用enum hack声明一个名为value的TMP变量。
         TMP可以将工作有运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率。
         TMP可被用来生成“基于政策选择组合”的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码。


          因为模板这块学的一般,就先简单总结下吧,以后用到可以再看~~ 害羞


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值