一个模板只有被使用到,才会被实例化,否则不会被实例化。对于一个实例化后的模板来说,未被调用的成员函数将不会被实例化,只有成员函数被使用时,C++标准才要求实例化他们

目前的编译器,在被一组实际参数实例化之前,只能执行有限的错误检查。

模板中的名称决议

  1. // scope of the template definition
  2. extern double foo ( double );
  3. template < class type >
  4. class ScopeRules
  5. {
  6. public:
  7. void invariant() {
  8. _member = foo( _val );
  9. }
  10. type type_dependent() {
  11. return foo( _member );
  12. }
  13. // ...
  14. private:
  15. int _val;
  16. type _member;
  17. };
  1. //scope of the template instantiation
  2. extern int foo( int );
  3. // ...
  4. ScopeRules< int > sr0;
  5. sr0.invariant();
  6. sr0.type_dependent();

对 invariant 的调用是 double 的那个函数;对 type_dependent 的调用是 int 的那个函数。

模板中对于一个非成员 name 的决议结果,是根据这个 name 的使用是否与“用以实例化该template的参数类型”有关而决定的。如果其使用互不相干,那么以模板声明作用域来决定 name;如果互有关联,那么以模板实例化作用域来决定name

name与实例化模板的参数相关的例子:比如template<typename T>然后调用的时候参数有T那么就是有关联的。

这意味着编译器必须保持两个作用域上下文:

  1. 模板声明作用域,用于一般的模板类;
  2. 模板实例化作用域,用于特定实例。

编译器的决议算法必须决定那一个才是合适的作用域,然后再其中搜寻适当的name。

TODO:异常处理后面再补。

7.3 运行期类型识别 (RTTI)

在C++中具备多态性质的 class,就是内含继承而来或者直接声明的虚函数。

将多态类的 type_info 作为一个 slot 加入类的 vtbl 即可。这样的策略可以降低额外负担。每个类对象只需要多花费一个指针。这个指针只需被设定一次,是编译期静态设定的,而非在运行期由类构造函数设定(只有 vptr 是这么设定)

dynamic_cast运算符提供运行期转型操作

  1. pfct* pf = dynamic_cast<pfct*>(pt);

dynamic_cast的真正成本:pfct 的一个类型描述器会被编译器产生,由 pt 指向的类对象的类型描述器*必须在运行期通过vptr获得
image.png

typeid运算符: typeid 可以返回const type_info&,用以获取类型信息。