effective C++读书笔记七——模板与泛型编程

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

       面向对象编程世界总是以显式接口(函数签名为中心)和运行期多态(通过virtual函数)来解决问题。而templates则是相反,通过隐式接口和编译期多态。隐式接口奠基于有效表达式。编译器多态,在templates的任何函数调用,造成template的具现化,使这些调用得以成功,这样的具现行为发生在编译期。

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

       1)声明templates参数时,前缀关键字classtypename可互换。

       2)在嵌套从属类型名称前应该使用关键字typename标识,但不得在base class list(基类列)或member initialization list(成员初值列)内以它作为base class修饰符。

       记住下面这个例子:

template<typename T>

class Derived:public Base<T>::Nested{     //base class list不允许typename

public:

    explicit Derived(int x)

       :Base<T>::Nested(x)      //mem ini list  中不允许typename

    {

typename Base<T>::Nested temp;//嵌套从属类型除上述两种情况外,都须加typename

       ......

    }

};

 

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

C++不进入“templatized base class观察”的行为失效。有三个办法,第一是在base class函数调用动作之前加上“this->;第二种方法使用using 声明式;第三种方法是明白指出被调用函数位于base class内,但这种不是一个令人满意的解法,因为如果被调用的是virtual 函数,上述的明确资格修饰会关闭“virtual 绑定行为”。

41.条款44:将与参数无关的代码抽离templates

       1)编写templates时,注意共性和变性的分析。

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

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

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

 

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

1)真实指针做得很好的一件事是支持隐式类型转换,derived class可以隐式转换为base class指针,“指向non-const对象”的指针可以转换为“指向const对象”。但智能指针却不行。同一个template的不同具现体之间并没有什么固有的关系(base-derived关系的BD两类型分别具现化某个template,产生出来的两个具现体并不带有base-derived关系)。

       2)通过member function templates(成员函数模板)生成“可接受所有兼容类型”的函数。

       template<typename T>

class SmartPtr{

public:

    template<typename U>

    SmartPtr(const SmartPtr<U>&other);

    //根据U对象创建对象t,而uv是同一个template的不同具现体.

    .....

};

缺点:有可能出现由base对象生成derived对象,没有约束性。

改进:

template<typename T>

class SmartPtr{

public:

    template<typename U>

    SmartPtr(const SmartPtr<U>&other)

       :heldPtr(other.get()){...}

    T* get()const{return heldPtr;};

   

    .....

private:

    T* heldPtr;

};

 

//这个行为只有当“存在某个隐式类型转换可将一个U*指针转化为一个T*指针”才能通过编译。

(1)  成员函数模板的效用并不限于构造函数,它们支持赋值操作,如果用于“泛

copy构造”或“泛化assignment操作”,你还是需要声明正常的copy构造函数和copy assignment操作符。

       如:

template <class T>

class shared_ptr{

public:

    shared_ptr(shared_ptr const&r);

    template<class Y>

    shared_ptr(shared_ptr<Y> const&r);

    shared_ptr& operator=(shared_ptr const&r);

    template<class Y>

    shared_ptr&operator=(shared_ptr<Y>const& r);

    ......

};

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

1template实参推导过程中从不将隐式类型转换函数纳入考虑。比如:

Rational<int> oneHalf(1,2);

Rational<int> result = oneHalf * 2; 

第二个实参(2)类型是int,编译器无法将2转换为Rational<int>.

(2)当我们编写一个class template,而它所提供之“与此template相关的”函数支持“所有参数之隐式类型转换”时,请将那些函数定义为“class template内部的friend函数”。

template <typename T> class Rational;

template<typename T>

const Rational<T> doMultipy(const Rational<T>&lhs, const Rational<T>&rhs);

 

template<typename T>

class Rational{

public:

    ...

friend const Rational<T> operator*(const Rational<T>&lhs, const Rational<T>&rhs)

    {return doMultipy(lhs,rhs);}

    ...

};

44.条款47:请使用traits classes表现类型信息

1STL迭代器五类:

l  Input迭代器,只能向前移动,一次一步,客户只可读取它们所指的东西,而且只能读取一次,模仿输入文件的阅读指针。实例:istream_iterators

l  Output类似input迭代器,它只能写,客户只可涂写它们所指的东西,而且只能涂写一次,模仿指向输出文件的涂写指针。实例:ostream_iterators

l  Forward迭代器,向前移动,读写其所指物一次以上,TR1hash容器可能为这一类

l  Bidirectional迭代器,可以向前,向后移动,常见的listsetmultiset,map,multimap迭代器

l  Random access迭代器,可执行迭代器算术,在常量时间内向前或向后跳跃任意距离,这样的算是很类似指针算术,因为它以内置指针为榜样,而内置指针也可被当作random access迭代器使用。实例:vector, deque, string属于这类。

2Traits并不是C++关键字或一个预先定义好的构件,它们是一种技术,也是一个C++共同遵守的协议,要求之一是内置类型和用户自定义的类型的表现必须一样好。

(3) traits class使得“类型相关信息”在编译期可用,它们以templates和“templates特化”完成实现

4)整合重载技术后,traits classes有可能在编译期对类型执行if…..else测试。

5)如何使用traits classes

l  建立一组重载函数(身份像劳工)或函数模板,彼此间的差异只在于各自的traits参数,令每个函数的实现码与其接受之traits信息相应和。

l  建立一个控制函数(身份像工头)或函数模板,它调用上述那些“劳工函数”并传递traits class所提供的信息。

45.条款48:认知template元编程

1template作用,可将工作从运行期转移到编译期,因而得以实现早期错误侦测和更高的执行效率。

2tmp可被用来生成“基于政策选择组合”的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码。

记住利用tmp实现阶乘的例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值