instatiation 实例化、实现 template模板、exception handling(EH)异常处理、runtime type identification(RTTI)执行期类型识别

第七章 站在对象模型的尖端

Template模板

Point< float >* ptr=0; 不会扩展 const Point< float >& ref=0;会被扩展 Point< float > temporary( float(0)); const Point< float >& ref=0; 因为reference并不是无物(no object)的代名词。0被视为整数,必须被转换为以下类型的一个对象。Point< float >。如果没有转换的可能,这个定义就是错误的,会在编译时被挑出来。 对于在int和long一致的架构中int 和long模板一般会生成两个实例 对于模板类的成员函数不是全被实例化,只有被使用的才被实例化。注意new运算符也有对应的函数、还有构造、析构、各种运算符等,只有被使用到的才被实例化,因为不同使用情况的实例类对应包含的成员函数不同。 实例化是在编译时(直接实例化到使用者的文件中)或链接时(编译器重新被激活,编译对应的实例,存储位置不一定) 在模板类中,所有有关于类型的检查,如果牵涉到类型参数,都必须延迟到真正的实例化操作之后才会发生。 当声明模板的作用域“定义出template”和使用模板的“实例化template”两处分别有不同参数类型的、同名class外函数时。并且模板类函数调用了此函数,那么调用函数名具体指向的哪个name:先判断被调用函数是否与实例化template的类型有关,无关则按照声明区域的范围选择,如果有关则按照实例化时的区域选择。

模板类中成员函数的实例化行为

不同编译器方案不同,没有认真看,有: directed-instantiation机制、use-driven automatic instantiation mechanism使用者驱动的自动实例化机制、automatic instantiation机制

异常处理

想要支持异常处理(Exception Handling),编译器的主要工作就是找到catch子句,以处理抛出来的exception(异常)。 异常处理的三个语汇组件

  1. 一个throw子句,它在程序某处发出一个exception。被抛出的exception可以是内建类型,也可以是自定义类型
  2. 一个或者多个catch子句,每一个catch子句都是一个EH,这个子句准备处理某种类型的exception,并且在封闭的大括号区段内提供实际的处理程序
  3. 一个try区段,它包含着一系列的叙述句statements,可能会引发catch子句起作用。

当一个exception被抛出,控制权用从函数调用中释放,寻找匹配的catch子句,若没有则会进入默认处理例程terminate()会被调用。

terminate()被调用成本好像很高? 出发异常处理要注意释放已经自己new的空间、共享内存等等资源。

当控制权被放弃后,对战中每一个函数调用也就被推离,这个过程叫做unwinding the stack。每个函数被unwind前,函数的local class objects的析构会被调用。 因此处理资源问题:将资源需求封装于一个class object内,并由析构函数来释放资源,这样会在被unwind时自动触发析构。但若此类资源被高频率的使用、释放则会复杂化。对EH的支持

  1. 检查所发生的throw操作函数
  2. 决定throw操作是否发生在try区段中
  3. 若是,则编译系统会将异常类型拿出来与每一个catch子句进行比较
  4. 若结果吻合,流程控制交到catch子句之中
  5. 如果throw的操作并没有发生在try区段中,或者是没有一个catch子句吻合,那么编译器必须进行以下操作 摧毁所有的active local objects;从堆栈中将目前的函数“unwind”掉;进行到堆栈的下一个函数中去;重复2~5步骤

处理异常时,catch(E &e)和catch(E? e)有区别,如果不用引用,此区间的一切操作都是对局部变量操作,不会被记录。如果对&e操作则会修改记录。但就算引用也是引用的最初throw e这个object的副本,最初object一直不会被修改,直到某一级别的catch不再继续throw时最初的object被销毁。

执行期类型识别

只有含有虚函数的类的声明或继承来的虚函数,才会编译器认为是具备多态性质的类(polymorphic class)。则会包含vptr,vptr第一项为type_info。 dynamic_cast运算符可以在执行期决定真正的类型,以保证向下转换的安全性。 对指针进行dynamic_cast,成功则返回指针,失败则返回0,成功返回的指针不一定和原始指针一样,因为可能会有相应偏移,因为base class subobject不一定和object指针一样,不一定是单一继承。 dynamic_cast对引用做操作,不能返回0表示失败。若成功继续运行,若失败抛出bad_cast异常。 通过typeid(a),a可以为对象、引用、指针、类型,可以获得一个type_info类实例的const引用。type_info中记录了类原始名、编码名等多种信息描述object。