7第七讲名空间和RTTI.pptVIP

  • 5
  • 0
  • 约1.72万字
  • 约 72页
  • 2016-08-15 发布于重庆
  • 举报
7第七讲名空间和RTTI

* 要点: 介绍本章的主要内容。 * * * * * * * * * * * * * * * * * * * * * 引用的dynamic_cast dynamic_castT(p) 如果p不是T类型的,会抛出一个bad_cast异常 class B {}; class D: public B {}; void f( D d) { B b = dynamic_castB(d); } * 先激活RTTI,如果编译器没打开RTTI支持,你要打开它; 对象所属类型必须是多态类族; 若使用dynamic_cast转换一个引用,则要使用异常处理机制,因为它可能抛出 std::bad_cast异常; 若使用typeid (*p)来检索对象的类型信息,又恰碰 p == NULL时,将抛出std::bad_typeid异常; 当使用dynamic_cast运算符转换一个指针时,定要检查结果是否为NULL. 使用RTTI的注意事项 * RTTI的出现不仅解决了异常处理机制中的问题,还能完成虚函数不能完成的工作; RTTI的是个总的概念,它涵盖了如下内容: 运算符typeid 运算符dynamic_cast 一个记载了对象的类型信息的type_info类 还维护着一个继承树,它表明了多态类族的is a 关系。 但RTTI和虚函数不是一回事。因为虚函数的动态决议并没有使用type_info的信息。“早在RTTI特征于1993年被引入C++之前,C++对多态的唯一支持就是对虚函数的动态决议操作。有了RTTI后,就能够在运行时查询一个多态指针或引用指向的具体对象的类型了.” RTTI和虚函数 * class B { public: virtual float fun() { return 0.1; } }; class D :public B { ……} void main() { B *p = new D; B r = *p; //无名对象照样有别名 couttypeid(p)==typeid(B*); //仅指向子类中父类部分 couttypeid(p)!=typeid(D*); //而非指向整个子类对象 couttypeid(r)==typeid(D); //引用的类型却是子类的 couttypeid(*p)==typeid(D); //间址访问的是子类对象 couttypeid(*p)!=typeid(B); //而非父类 couttypeid(r)==typeid(B*); //引用的地址是父类的 couttypeid(r)!=typeid(D*); //而非子类的 } 用typeid分析指针与引用的区别 画出图示! 运行结果全是真,后面是解释。 * 对于函数模板可以这样调用: int m1 =MAX(10,15); 也可以这样调用: int m2 =MAXint(10,15); 这叫作显式调用。 这种形式和C++新增的四个cast运算符何其相似! 其实,这四个运算符就是四个函数模板。于是我们也可以如法炮制出我们需要的转换函数来。 从函数模板看四个转换运算符 templatetypename DestType,typename SrcType DestType static_cast( SrcType src) { return DestType( src); //使用C-style的强转 } 于是我们可用函数模板来自定义转换函数: templatetypename DestType,typename SrcType DestType My_cast( SrcType src) { return DestType( src); } C++将支持以下的调用: int * p = My_castint * (100); char c = My_castchar ,int (100); double p = My_castdouble,long (100); 函数模板可用来自定义转换函数 对于许多有过程编程背景的人来说,要他们不把程序组织成为一组switch语句非常困难。他们可能会运用RTTI来完成任务,但会在代码维护阶段丢失多态性的非常重要的价值。 C++的意图是:尽可能地使用虚函数,必要时才使用RTTI。当然,要想充分使用虚函数,我们必须控制基类的定义。但随着程序的扩大,我们可能发现基类并没有我们想要的虚函数,如果基类来自类库或其他由别人控制的来源,就可以用RTTI作为一种解决办法:我们可以派生一个新类,并加上我们的成员函数。在代码的其他地方可以检测到新增类型和调用的那个成员函数。这不会破

文档评论(0)

1亿VIP精品文档

相关文档