c++对象模型研究7:站在对象模型的顶端
template
在C++发明阶段,C++之父Stroustrup和贝尔实验室的C++小组对原先的宏方法进行了修订,对其进行了简化并将它从预处理范围移入了编译器。这种新的代码替换装置被称为模板,而且它变现了完全不同的代码重用方法:模板对源代码重用,而不是通过继承和组合重用对象代码。当用户使用模板时,参数由编译器来替换,这非常像原来的宏方法,却更清晰,更容易使用。
未使用的template member function不应该被实例化。
对于template的错误检查,只有在实例化操作时才会进行类型类型检查,而所有的语汇(lexing)错误和解析(parsing)错误都会在处理template声明的过程中被表示出来。也就是用到了语法分析器。
在目前的编译器中,面对一个template声明,在它被一组实际参数实例化之前,只能施以有限的错误检查。
template中的名称决议法,分为 scope of the template definition 和 scope of the template instantiation.
template之中,对于一个nonmember的决议结果,是根据这个name的使用是否与“用以实例化该template的参数类型”有关而决定。如果互不相关,则使用“scope of the template declaration”来决定name,否则以“scope of the template instantiation”来决定name。
函数的决议结果,只和函数的原型有关,和函数的返回值没有关系。
对于member function的实例化行为,编译器设计者需要考虑以下3种问题:
1.编译器如何找打函数的定义? --> 答案是产生template program text file, 有点类似header
2.编译器如何能够只实例化程序中用到的member function? --> 解法方法之一,是忽略此项要求,只要class的object被实例化,就全部产生出来;另一个解决方法是模拟链接操作,检测看看哪个函数真正需要,然后只为他们产生实例
3.编译器如何组织member definition在多个 .o文件中被实例化? -->方法是产生多个实例,但只在链接器中保存一个。
对于member function,每个member function的地址都被放在active classes的virtual table中。
如果virtual table被产生出来,每个virtual function 都必须被实例化。
异常处理
欲支持exception handling,编译器的主要工作是找到catch子句,以处理被抛出来的exception。
执行期类型识别
dynamic_cast运算符可以在执行期决定真正的类型。
如果downcast是安全的,也就是说base type pointer指向一个derived class object。这个运算符会传回被适当转换过的指针。
如果downcast是不安全的,这个运算符会传回0。
dynamic_cast的成本是编译时会产生一个类型描述器。
执行期对一个class指针施以dynamic_cast运算符,会返回true或false,true指的是返回真正的地址,false表示没有指向任何对象。
dynamic_cast运算符也适用于reference。
若将一个reference设为0,会引起一个临时对象被产生出来,该临时对象的初值为0,这个reference然后被设定成该临时对象的别名。
如果真正参考到derived class,downcast会继续执行程序,反之,会跑出一个bad_cast exception操作。
typeid运算符
typeid运算符传回一个const reference。类型为type_info.
RTT1只适合于多态类,但是typeid同时也适用于内建类型。 如typeid(double) 会传回一个 const type_info&。这个时候type_info object是静态取得,而非执行期取得。
效率、弹性
传统的C++对象模型提供有效率的执行期支持。这份效率,再加上与C之间的兼容性,造成了C++的广泛被接受度。然而,在某些领域方面,像是动态共享函数库、共享内存、以及分布式对象方面,这个对象模型的弹性还是不够。
ps:如果你对于COM感兴趣,推荐两本理想的书籍:
《Essential COM》
《Inside COM》
阅读顺序《Essential COM》一二章->《Inside COM》
参考:
《深度探索C++对象模型》
http://blog.csdn.net/zone_programming/article/details/50412823