Effective C++笔记part 7、8、9

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

classes和Templates都支持接口和多态:

对class而言接口是显式的,以函数签名为中心。多态是通过virtual函数发生于运行期。

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

42.了解typename的双重意义

  1. template<class T> class Widget;//使用“class

template<typename T> class Widget//使用“typename”

声明template参数时,用关键字class和typename意义完全相同

  1. template内出现的名称如果相依于某个template参数,称作从属名称

如果从属名称在class内呈嵌套状,称之为嵌套从属名称

不依赖任何template参数的名称,称之为非从属名称

如果解析器在template中遭遇一个嵌套从属名称,它便假设这个名称不是个类型,除非告诉它是。

typename C::const_iterater iter;//一般性规则:在嵌套从属名称前加一个typename关键字

  1. 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

  1. templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生想依关系
  2. 因非类型模板参数而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数
  3. 因类型参数而造成的的代码膨胀,往往可降低,做法是让带有完全相同二进制表述的具现类型共享实现码

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

使用成员函数模板生成“可接受所有兼容类型”的函数

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

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

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

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

  1. TR1导入许多新的traits classes 用以提供类型信息,包括is_fundamental<T>(判断T是否是内置类型),is_array<T>(判断T是否为数组类型),is_base_of<T1,T2>(T1和T2是否相同,或T1是T2的base class)
  2. Traits classes使得“类型相关信息”在编译期可用,他们以templates和“templates特化”完成
  3. 整合重载技术后,traits classes有可能在编译期对类型执行is…else测试

48.认识template元编程

TMP模板元编程

  1. TMP将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率
  2. TMP可以被用来生成“基于政策选择组合”的客户定制代码,也可以用来避免生成对某些特殊类型并不适合的代码。

49.了解new-handler的行为

一个设计良好的new-handler函数必须做以下事情:

  1. 让更多内存可被使用。程序一开始执行就分配一大块内存,而后new-handler第一次被调用,将它们释还给程序使用。
  2. 安装另一个new-handler
  3. 卸除new-handler,也就是将null指针传递给set_new_handler。一旦没有安装任何new-handler,operator new会在内存分配不成功时抛出异常。
  4. 抛出bad_alloc异常,这样一场不会被operator new捕捉,因此会被传播到内存索求处
  5. 不返回,通常调用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程序库包括数十个类目:

字符串与文本处理、容器、函数对象和高级编程、泛型编程、模板元编程、数学和数值、正确性与测试、数据结构、语言间的支持、内存、杂项

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章