站在对象模型的尖端
7.1 Template
Template的“具现”行为 (template instantiation)
编译器看到template的声明,并不做任何的事情,只有等到template instantiation的时候, 定义出一个template class object 或者 template class refrence(引用必须初始化),才会相应的准备template class 内部的数据排放等等,此时在template class 内部声明的static data member 也才会有内存。而仅仅声明一个template class pointer 并不会有template instantion .注意: 在template class instantiation的时候,其内部的member functions 并不同时跟着被“实体”化。只有在member functions 被使用的时候, C++ Standard才要求他们被具现出来。原因有二:可能某个程序只使用其中的几个member functions,没有必要为所有的member function 都具现,消耗大量的空间和时间;另外,由于template classs 是generic programming ,所以某些member function 并不是对任何带入的class都是可用的。所以如果我们同时具现所有的member function,往往可能会造成“编译时期的错误”,而恰恰程序中根本就不会使用到该“不合法”的member function. 那么,这些member function何时具现呢?有两种策略:1、在编译的时候 ;2、在链接的时候
Template的错误报告根据刚才所说,member function 由于在程序中被使用的时候才会局限,所以在template class definition的时候不会检查和类型相关的错误,而只是检查语法词汇错误等与类型无关的错误。
Template中的名称决议方式在C++ Standard中, "scope of the template definition "—— “定义出template"的程序 ; "scopte of the template instantiation"—— "具现出template"的程序在template之中, 对于一个nonmember name的决议结果是根据这个name的使用是否与”用以具现该template的参数类型“有关而决定的。如果其使用互不相关,那么使用”scopte of the template declaration"决定其name;如果使用互有关联马么就使用“scope of the template instantiation"来决定name
7.2 异常处理
支持EH,会使那些拥有member class objects 或者base class sunjects的classes的constructor更复杂。一个class 如果被部分构造,则其destructor必须被是性欲哪些已经被构造的subject 或者 member objects身上。 这一段话并不和More Eff上面的第十款相违背。因为这里的member class objects 是在堆栈中创建的,而More Eff条款十讲的是在堆里面为member class pointer分配内存,如何防止"member class pointer"的未及时删除引起的memory leak .
对Exception Handling的支持当一个exception 发生的时候,编译器将会完成一下事情:1、检查发生throw操作的函数;2、决定throw操作是否发生在try 区段中;3、若是,则编译系统必须把exception type 拿来和每一个catch子句比较4、如果比较温和,则程序会交到catch这一区段5、如果throw 不再try段,或者在try 段,但是没有吻合的catch子句,就会释放active local object,然后移动堆栈指针,到调用者的函数去! 重复2——5
Exception匹配过程中发生的事情可以参考More Eff
7.3 执行期类型识别(RTTI)
千万尽量不要在程序中使用RTTI,参看More EFf为了支持type_Sage downcast,需要安排一定的空间和时间用于存放和查询某个class object的数据类型。恰好可以和VTable相结合起来。
dynamic_casrt运算符可以在执行期间决定真真的类型,如果downcast指针是安全的,那么这个运算符会传回被适当转型过的指针;如果不安全,则传回0 .而dynamic_cast相当于((type_infor*)(pt->vptr[0]))->_type_descriptor dynamic_cast运算符也适用于reference,但是dynamic_cast失败,不是返回0,而是抛出异常
另外,还可以利用Typeid运算符,typeid运算符传会一个const reference,类型为type_info.而type_info是一个class,可以在VC的typeinfo.h头文件中找到。
程序:
# include <iostream.h> #include<typeinfo.h> class B void main() cout<<typeid(pb).name()<<endl; |