《深度探索c++对象模型》学习笔记 - 7 站在对象模型的顶端

 

1.         当异常被抛出时,控制权会从函数调用中转移出来。栈中局部变量被析构,函数调用栈被unwinding

2.         new[15],在第10个的时候发生了异常,那么前面的9个数据会在try{}大括号结束的时候释放,即所谓的unwind

3.         关于异常的性能、产生临时对象、匹配等问题,看代码和Exceptional C++

4.         具备多态性质的类(polymorphic class),必须内含着继承而来或者自己定义的virtual function

5.         对于RTTI的支持,把RTTI对象放到vtbl的第一个slot里面,这样对空间是:一个类只有一个指针的额外支出。

6.         Dynamic_caststatic_cast要花费更多的性能(检查RTTI释放匹配、指针offset等),但是安全性更好。

7.         对引用施加Dynamic_cast1)成功;或2)抛出bad_cast异常;对指针施加:1)成功;2)返回0指针。

8.         使用typeid()进行判断,合法之后再进行Dynamic_cast,这样就能够避免对引用操作导致的bad_cast异常: if(typeid(rt) == typeid(rt2)) …。但是如果rtrt2本身就是合法兼容的话,就会损失了一次typeid的操作性能。

 

示例代码:

#ifndef ch7_h #define ch7_h #include <typeinfo.h> namespace ch7{ // p312,RTTI namespace rtti{ class B{public: virtual f(){};}; class D:public B{public: virtual f(){};}; void test(){ { B* b = new D(); D* d = dynamic_cast<D*>(b);// here ok if (d == NULL) { printf("dynamic_cast<D*>(d) 1 error/n"); } b = new B(); d = dynamic_cast<D*>(b);// here error if (d == NULL) { printf("dynamic_cast<D*>(d) 2 error/n"); } } { try { B b; if (typeid(&b) == typeid(D)) { D& d = dynamic_cast<D&>(b);// here error printf("can convert D& d = dynamic_cast<D&>(b)/n"); } else{ printf("cannot convert D& d = dynamic_cast<D&>(b)/n"); } }catch (...){ printf("D& d = dynamic_cast<D&>(b) error/n"); } } } } // p300,异常的匹配 namespace exceptions{ class CMyException{}; class CMyException2: public CMyException{}; class throwcls{ public: throwcls(){ throw new CMyException(); } }; void test(){ try{ throwcls* cl = new throwcls(); } // 如果把CMyException放到CMyException2前面,那么会出现编译warning: // 认为基类在子类前面的话,子类永远也不可能被使用 catch (CMyException2* ){} catch (CMyException* ) {} catch (int* ) {} /* int m = 0; try{ throw; // 这个throw,会首先被认为没有默认处理:抛出异常对话框; // 然后,会分别执行下面的两个catch,结果是m==2,很奇怪 } catch (CMyException* ){ m++; } catch(...) { m++; } // m == 2; */ } } // p302,数组构造的异常处理 namespace arrays{ class throwcls{ static int n; public: throwcls(){ if ( 10 == n) throw new int(8); else n++; } ~throwcls(){ n = 0; } }; int throwcls::n = 0; void test(){ try { throwcls* cl = new throwcls[15]; } //C // ******** // 当new[n](n=15),在第m(m=10)个的时候发生了异常, // 那么前面的9个数据会在try{}大括号结束的时候析构, // 即所谓的unwind。 // 这个析构不会在A处,或者在B处,而是在更前面的C处进行 // ******** catch (int* ) { int j = 0; // A } int j = 0; // B } } // main test void test(){ printf("ch7 begin/n"); rtti::test(); exceptions::test(); arrays::test(); printf("ch7 end/n"); } }; #endif

你可能感兴趣的:(C++,c,function,null,Arrays,Class)