41.了解隐式接口和编译期多态
classes和Templates都支持接口和多态:
对class而言接口是显式的,以函数签名为中心。多态是通过virtual函数发生于运行期。
对template参数而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析发生于编译期。
42.了解typename的双重意义
- template<class T> class Widget;//使用“class
template<typename T> class Widget//使用“typename”
声明template参数时,用关键字class和typename意义完全相同
- template内出现的名称如果相依于某个template参数,称作从属名称
如果从属名称在class内呈嵌套状,称之为嵌套从属名称
不依赖任何template参数的名称,称之为非从属名称
如果解析器在template中遭遇一个嵌套从属名称,它便假设这个名称不是个类型,除非告诉它是。
typename C::const_iterater iter;//一般性规则:在嵌套从属名称前加一个typename关键字
- typename关键字只用来验明嵌套从属类型名称,其他名称不该有他存在。例外是,typename不可以出现在 base class list内的嵌套从属类型名称之前,也不可在member initialization list(成员初值列)中作为base class修饰符
43.学习处理模板化基类内的名称
当编译器遭遇继承一个template class时,并不知道它继承的是哪一个class(在具现化之前)。
template<>语法象征这既不是template也不是标准class.
令c++“不进入templatized base class观察”行为失效的三种方法:
1 在base class函数调用动作之前加上this->
2 使用using声明式 using 基类名<template名>::要调用的函数
3 明白指出被调用的函数位于base class内,调用时用 基类名<模板名>::函数名
44.将与参数无关的代码抽离templates
- templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生想依关系
- 因非类型模板参数而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数
- 因类型参数而造成的的代码膨胀,往往可降低,做法是让带有完全相同二进制表述的具现类型共享实现码
45.运用成员函数模板接受所有兼容类型
使用成员函数模板生成“可接受所有兼容类型”的函数
如果声明member templates用于“泛化copy构造”或“泛化assignment操作”,还是需要声明正常的copy构造函数和copy assignment操作符
46.需要类型转化时为模板定义非成员函数
当编写一个 class template,而它所提供的“与此template相关的”函数支持“所有参数之隐式类型转换”时,将那些函数定义为:class template内部的friend函数
47.使用traits classes表现类型信息
- TR1导入许多新的traits classes 用以提供类型信息,包括is_fundamental<T>(判断T是否是内置类型),is_array<T>(判断T是否为数组类型),is_base_of<T1,T2>(T1和T2是否相同,或T1是T2的base class)
- Traits classes使得“类型相关信息”在编译期可用,他们以templates和“templates特化”完成
- 整合重载技术后,traits classes有可能在编译期对类型执行is…else测试
48.认识template元编程
TMP模板元编程
- TMP将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率
- TMP可以被用来生成“基于政策选择组合”的客户定制代码,也可以用来避免生成对某些特殊类型并不适合的代码。
49.了解new-handler的行为
一个设计良好的new-handler函数必须做以下事情:
- 让更多内存可被使用。程序一开始执行就分配一大块内存,而后new-handler第一次被调用,将它们释还给程序使用。
- 安装另一个new-handler
- 卸除new-handler,也就是将null指针传递给set_new_handler。一旦没有安装任何new-handler,operator new会在内存分配不成功时抛出异常。
- 抛出bad_alloc异常,这样一场不会被operator new捕捉,因此会被传播到内存索求处
- 不返回,通常调用abort或exit。
允许用户指定一个函数,当内存分配无法满足时被调用
Nothrow new是一个颇为局限的工具,因为他只适用于内存分配;后继的构造函数调用还是可能抛出异常。
50.了解new和delete的合理替换时机
如果将“new所得内存”delete失败会造成内存泄漏,如果在“new所得内存”上多次delete会导致不确定行为
很多时候需要写个自定的new和delete,包括改善性能、对heap运用错误进行调试、收集heap使用信息。
51.编写new和delete时需固守常规
operator new应该内含亦歌无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler。他也应该有能力处理0bytes申请。Class专属版本则还应该处理“比正确大小更大的(错误)申请”
operator delete应该在收到null指针时不做任何事。Class专属版本则还应该处理“比正确大小更大的(错误)申请”
52.写了placement new也要写placement delete
53.不要轻忽编译器的警告
54.让自己熟悉包括TR1在内的标准程序库
55.让自己熟悉Boost程序库
Boost程序库包括数十个类目:
字符串与文本处理、容器、函数对象和高级编程、泛型编程、模板元编程、数学和数值、正确性与测试、数据结构、语言间的支持、内存、杂项