[温故而知新] 《深度探索c++对象模型》——站在对象模型的尖端

前言

终于到最后一章啦,准备迎接新的篇章,刚好“霹雳布袋戏”要出新的剧集了,期待ing。

这里写图片描述

这章也是一些零散的知识点。

1. 模版的名称决议

直接上代码:

//scope of the template definition
extern double foo(double);

template < class type >
class ScopeRules{
public:
    void invariant(){
        _member = foo( _val );
    }
    type type_dependent(){
        return foo( _member );
    }
private:
    int _val;
    type _member;
}

//scope of the template instantiation
extern int foo(int);

ScopeRules<int> sr0;
sr0.invariant();
sr0.type_dependent();

这里有两个foo,两个方法调用里的foo分别对应哪个?

注意两点就ok了:
1.模版,并不是实例化的时候,就把所有的方法都实例化。
比如说这个模版里有1000个方法,都是与模版类type 相关的,而实例化模版后只用到其中的几个,那如果在实例化的时候就把1000个方法都实例化那岂不是白白做了许多无用功?所以,有些编译器会有个策略,就是只实例化需要用到的方法或者成员,其它不实例化。
回到开头的代码上,如果不调用sr0.type_dependent(); 那么实例化这个方法并没什么卵用。

2.模版里用到的函数调用符号决议规则:如果这个函数调用符号与模版类型type 没半毛钱关系,那这个函数调用符号就是在模版定义的地方找相应的符号;如果这个函数调用符号与模版类型type有关联,那么这个函数调用符号应该在实例化模版的地方找相应的符号。

所以,invariant() 里的foo应该找模版定义的地方里的foo; 而 type_dependent() 里的foo应该在它实例化的时候找相应的foo。

2. 显式模版实例化

显式要求在一个文件中将整个class template实例化
template class Point3d;

针对一个template class 个别member function:
template float Point3d::X() const;

3. 抛出Exception时保证的语意

c++的实现中,正常执行时,在每一个函数被推离堆栈之前,函数的 local class objects 的 destructor会被调用。
如果exception抛出时,exception之前的local object 会析构,后面的代码不执行!

所以才需要那些什么auto_ptr什么的包装一层,也就是在前面声明一些auto_ptr,即使遇到exception,auto_ptr 的析构函数也会被调用。

4. try catch 的实现原理

把函数体分为三种区域,用一个表格来标识,用类似eip(指令的位置来判断)
try区域外,没有active local object
try区域外,有active local object
try区域内
所以实现Exception handler时,就可以根据这些区域,找出有哪些local objects 。当Exception抛出时,也就知道哪些local objects需要调用析构函数。

5. Exception 必须包含所有base class的类型信息

c++ 的 RTTI(Run time type identification)执行期类型识别,有的编译器是在virtual table里的一个指针指向具体的 type_info结构来实现的。

假如产生一个exVetex异常(exVetex继承自exPoint),下面两种写法有些不同:


//1.
catch(exPoint p){
    throw; //继续抛出的是exVetex,p是一个临时对象
}

//2.
catch(exPoint &p){
    throw;//继续抛出的是裁剪后的exPoint
}

只有在一个catch子句评估完毕并且知道它不会再抛出exception之后,真正的exception object才会被销毁。

6. static_cast 与 dynamic_cast

static_cast 静态强制转换,不管什么类型,直接转,不安全

dynamic_cast执行期转换,对于指针,成功返回地址,失败返回0。
对于reference,成功接着执行,失败抛出bad_cast异常。抛出异常而不是用0表示失败的原因:
引用不能用0,引用0的话是产生一个临时对象,所以不能用0代表引用无物,所以抛出异常。所以需要用dynamic_cast的话需要try catch …

感觉try catch+dynamic_cast 蛋疼的话,还可以这样:

if(typeid(..) == typeid(…)){
    ..static_cast<>...
    //typeid 返回的是一个typeInfo的结构
}

好的,终于可以把这本十分蛋疼又别扭的书扔掉啦!Congradulations!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值