C++复习8.异常处理和RTTI

C++异常处理和RTTI技术 20130930

1.异常处理的基本知识

C语言中是没有内置运行时错误处理机制,对于错误发生的时候使用的几种处理机制:

函数返回彼此协商后统一定义的状态编码来表示操作成功、失败或者是其他类型的错误;使用全局变量来保存错误编码,每一个使用到他的函数在开始的时候都会检查他的值,并且每一个函数的操作结果都会写到这个全局变量中,如使用errno表示任何一个函数调用返回后产生的错误码;出错的时候终止程序的运行。

         但是这些传统的方法村下载一些问题:没有形成统一的标准;将正常的代码和错误处理程序紧紧的绑定在一起;有些函数式咩有返回值的;全局的错误变量,不仅在函数的开头检查它,而且有时候还要把他清零;发生错误的时候,使用exit或者abort粗暴的退出程序是很不友好的方式。

         C++中的解决办法就是:C++异常处理机制。允许从异常抛出点把任意数量的信息已类型安全的方式传递给异常处理器;对于没有抛出异常的代码段,他不会带来任何的二外的时间和空间开销;保证程序抛出的任何一个异常都能够被适当的处理器捕获;通过一种组合方式可以是程序员写出处理一组异常的处理器;能够直接使用在多线程程序中。。。

2.异常处理C++

          在C++中如果一个异常在抛出点没有被处理的话,那么他会一直被抛向上层的调用者,直到Main函数遇到一个可以处理该异常的处理器,否则就会调用terminate()函数技术程序。

         异常类型和异常对象:任何一种类型都是可以当做异常类型,包括基本的数据类型的变量常量,任何类型的指针等等。但是我们一般不会直接使用基本数据类型的对象作为异常,因为这就退回到最开始处理异常的地步。

         异常处理是一种程序控制结构,它包括4个组成部分:抛出异常、提炼异常、捕获异常、异常对象本身。C++异常处理的关键字 throw try{} catch{}. 异常抛出点和异常捕获点距离肯呢过会很远,异常抛出点可能深埋在底层软件模块内,而异常捕获点常常在高层组价中;异常捕获却必须和异常提炼块结合使用,并且可以通过异常组合在一个地点捕获多种异常。

         异常的匹配规则:必须保存每一个throw语句抛出的异常对象的类型信息和每一个catch子句的参数类型信息,其目的就是在运行的时候执行异常对象和异常处理器的类型匹配。

         当异常抛出时局部对象如何释放:throw语句就像一个goto语句,因此他本质上是一种程序控制手法,在正常的情况下每一个函数在结束前的一刻都会调用其创建在堆栈中的每一个对象的析构函数来释放其占用的资源。但是当函数执行遇到异常抛出的时候,妖魔进入当前函数的一个catch快,要么将异常传递给上层调用者,同时当前的函数结束,函数内部的局部对象如何处理?

         引入Resource Acquisition is initialization思想,在初始化阶段请求资源,对象销毁的时候释放资源。在构造函数中申请资源(内存、文件、通信设备等等),在析构函数中释放资源。

         异常处理机制保证:所有从try到throw语句之间构造的局部对象的析构函数将被自动调用,然后清退堆栈的内容,一直上溯到main函数。

         如果无法判断异常的类型则我么可以使用catch(void*) 处理那些不知道是什么类型的异常,但是要放倒最后面,否则所有的异常都会被它处理掉。

3.虚函数面临的问题

         在介绍RTTI之前,首先了解一下虚函数的不足:

         一般来说虚成员函数可以满足对象的动态类型匹配的需要。一个定义良好的类层次结构应该为基类中声明的每一个虚成员函数定义有意义的操作。但是对于公共类型的接口对于不同的子类可能不适用。这里我们便需要RTTI(运行时类型信息)的地方

4.RTTI以及其构成

         异常操作不是在编译的时候匹配好的,而是在运行的时候才会执行具体类型匹配操作。所以这里需要的是在运行期间检查每一个对象类型的信息的手段。一个异常类型可能是多态类型,当抛出的异常对象为派生了对象的时候,如果找不到确定的处理过程就应该尝试匹配其基类的处理过程,这也在运行的时候检查一个对象的类型信息。这也需要RTTI机制

         如果支持运行时对一个对象确切类型的检索,就需要改变对象内存映像,比如插入一个指针类指向器类型信息。虚拟机制出现之后,类型信息放在vtable中;RTTI技术不仅需要额外的内存开销(为每一个类型增加一个type_info对象),而且在运行的时候检索对象的类型信息需要一定的时间开销;在多数情况下,虚函数的功能对于运行时对象的匹配已经足够了。

         但是在C++中支持多种继承,静态的类型检查和动态函数的绑定不能够满足正确的判断所以RTTI和type_info被加入到C++中。

         为了能够在运行的时候获得对象的类型信息type_info,C++增加了两个运算符:typeid 和dynamic_cast<>, type_info常用的三个成员函数: operator==() operator!=() 和 name()。

         typeid运算符:就像sizeof一样是C++语言直接支持的,它对一个对象或者类型名作为参数,返回一个匹配 const type_info对象,表明对象的确切类型。

         typeid(object) == typeid(Television)

         另外static_cast<>的用途:强制的类型转换。

         dynamic_cast<dest_type>(src);这样的话如果双src和dest_type之间有关系,则可以转换,否则转换失败。

         dynamic_cast<>可以用来转换指针和引用,但是不能转换对象,如果转换的目标类型是指针,如果转换失败则返回NULL指针;但是如果是引用则会抛出异常std::bad_cast,因为不存在NULL的引用。

         另外dynamic_cast<>是通过该对象的vptr检查位于类型的vtable中的第一个solt的type_info,因此dynamic_cast只能够用于多态类型的对象,否则检出限编译错误。

         

原文地址:https://www.cnblogs.com/hbhzsysutengfei/p/3409456.html