《Effective C++》知识点(7)--模板与范型编程

41. 了解隐式接口和编译期多态

     41.1 面向对象编程的世界总是以显式接口和运行期多态(polymorphism)解决问题。   

     41.2 类和模板都支持接口和多态。

接口多态
类class显式的,基于函数签名通过虚函数发生于运行期
模板template隐式的,基于有效表达式通过template具体实现和函数重载解析发生于编译期
42. 了解typename的双重意义

     42.1 声明template参数时,<class T>和<typename T>的意义完全相同。 

     42.2 模板函数里的几种变量名称

变量名称英文定义
从属名称 dependent names依赖于某个template参数
嵌套从属名称nested dependent names从属名称在class内呈嵌套状
嵌套从属类型名称nested dependent type names嵌套从属名称并指向某种类型
非从属名称non-dependent names不依赖于任何template参数

             缺省情况下解析器认为嵌套从属名称不是个类型,除非你告诉它是(在前面放typename)

    42.3 "typename必须作为嵌套从属类型名称的前缀词"这一规则的例外是,typename不可以出现

            在base classes list内的嵌套从属类型名称之前,也不可在member initialization list中作为

            base class修饰符。 

    42.4 使用typedef定义嵌套从属类型名称(如果名字很长)的别名。

    42.5 typename在不同编译器上表现不同,可移植性差。 

43. 学习处理模板化基类内的名称

    43.1 "template<>"表示模板全特化,这既不是template也不是标准class,而是个特化版的具体

            某个类的template。一旦类型参数被定义,再没有其它template参数可供变化。

    43.2 基类模板可能被特化,而特化版本可能不提供和一般性模板相同的接口。所以编译器拒绝

            在模板化基类内寻找继承而来的名称(函数)。 

    43.3 继承类模板内调用模板化基类函数的三个方法

        a. 在基类函数调用动作之前加上"this->"。

        b. 使用using声明式,在继承类了声明基类函数。

        c. 明白地指出被调用的函数位于基类内(不适合虚函数)。

44. 将与参数无关的代码抽离templates

     44.1 Templates生成多个类和多个函数,所以任何template代码都不该与某个造成膨胀的

             template参数产生相依关系。注意template代码中,重复是隐晦的。

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

             template参数。

     44.3 因类型参数而造成的代码膨胀,往往可降低,做法是让带有完全相同二进制表述(比如指针

             类型)的具现类型共享实现码。

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

     45.1 请使用成员函数模板生成"可接受所有兼容类型"的函数。

     45.2 如果声明member templates用于"泛化copy构造"或"泛化assignment操作",你还是需要声

             明正常的copy构造函数和copy assignment操作符。

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

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

     46.2 template class内的friend声明式可以指涉某个特定函数。使用friend是目的是支持"所有参

             数的隐式类型转换"。

     46.3 为了让类型转换可能发生于所有实参身上,我们需要一个非成员函数;为了令这个函数被

             自动具现化,我们需要将它声明在class内部;而在class内部声明非成员函数的唯一办法

             就是令它为friend。这里使用friend与它的传统用途"访问class内非public成分"没有关系。  

47. 请使用traits classes表现类型信息

     47.1 STL的5种迭代器分类

类型描述代表
Input只能向前,一次一步,只读且一次istream_iterators
Output只能向前,一次一步,只写且一次ostream_iterators
forward可读写一次以上(单向链表),继承自inputslist、tr1::hashed?
bidirectional可向前或向后移动,继承自forwardlist、set、map
random access可在常量时间内向前或向后跳跃任意距离,继承自bidirectionalvector、deque、string

    47.2 Traits

            Traits并不是C++关键字或一个预先定义好的组件;它们是一种技术,也是一个C++程序员

            共同遵守的协议。它对内置类型和用户自定义类型的表现必须一样好。习惯上,traits总是

             被实现为structs,但它们往往被称为traits classes。Traits classes使得"类型相关信息"在编

             译期可用,以模板和模板特化完成实现。整合重载技术后,traits classes有可能在编译期

             对类型执行if...else测试。

    47.3 设计并实现一个traits class

          a. 确认若干你希望将来可取得的类型相关信息。

          b. 为该信息选择一个名称。

          c. 提供一个template和一组特化版本,内含你希望支持的类型相关信息。

    47.4 如何使用一个traits class

          a. 建立一组重载函数(劳工函数)或函数模板,彼此间的差异只在各自的traits参数。令每个函

              数实现码与其接受之traits信息相对应。

          b. 建立一个控制函数(工头)或函数模板,它调用上述那些"劳工函数"并传递traits class所提供

              的信息。

48. 认识template元编程

       TMP(模板元编程),是编写基于模板的C++程序并执行于编译期的过程。

    48.1 TMP可将工作由运行期移到编译期,因而得以实现早期错误侦测和更高的执行效率(较小的

            可执行文件、较短的运行期、较少的内存需求),缺点是编译时间变长了。

    48.2 TMP可被用来生成"基于政策选择组合"的客户定制代码(如Strategy、Observer、Visitor),

             也可用来避免生成对某些特殊类型并不适合的代码。TMP里的循环是用递归完成的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值