2.14 MFC的异常处理

程序运行中的有些错误是可以预料但不可避免的,这是要力争做到允许用户排除环境错误,继续运行程序;至少要给出适当的提示信息。传统错误处理方法大致可以分为返回码机制和全局变量两种。

(1)返回码机制

这种处理错误的方法比较实用和简单,这也是经常采取的手段之一。对于小型的程序来说这种异常处理机制的缺点暴露不明显,对于一个需要多人开发的软件程序来说,它的弊端就非常明显。因为对于一个模块的实现者来说有的人返回值0代表错误;有的人返回值0代表正确,非0代表错误。解决方法可以用一致性的条文来控制。通常,这些返回码就在一个公共的.h文件中以宏的形式存在。这样暂时解决了团队之间的一致性,但是这些都不是标准,兼容性太差。对于如此多的返回码要分别解释各自的意义,从调用者的角度来说,需要分别对返回码进行检查来处理异常,这样的代码往往就显得非常的臃肿,大大降低了可读性。

(2)全局变量

通过用一个全局变量来表示一次操作是否成功,这个方法在多线程中就非常头痛。另外,在每次处理完异常之后就要复位这个变量,如果忘记这个步骤,就会引起其他操作的误解。

更好的方式是通过异常处理,异常处理是由程序设计语言提供的运行时刻错误处理的一种方式。通过异常处理,程序可以向更高的执行上下文传递意想不到的事件,从而使程序能更好地从这些异常事件中恢复过来。我们在学习C++的时候已经接触过C++中的异常处理了,现在我们介绍MFC中的异常处理。MFC通过异常处理类和宏的联合使用来实现MFC中的异常处理。

MFC把异常处理封装到CException类及其派生类中,CException类是所有异常类的基类,它是一个抽象类,不能使用它的对象,只能创建它的派生类的对象。它有两个公用函数GetErrorMessage和ReportError,分别用于查找描述异常的信息和为用户显示一个错误信息的信息对话框。

如下表所示,给出了MFC提供的预定义异常类,这些类都从CException派生而来。

为了使用这些异常类,MFC还提供了THROW、THROW_LAST、TRY、CATCH、AND_CATCH、END_CATCH宏来处理异常。这些宏本质上也是标准C++的try、catch和throw的进一步强化。这些宏在使用语法上,有如下特点:

● 用TRY块包含可能产生异常的代码;

● 用CATCH块检测并处理异常。要注意的是,CATCH块捕获的不是异常对象,而是指向异常对象的指针。此外,MFC靠动态类型来辨别异常对象;

● 可以在一个TRY块上捆绑多个异常处理捕获块,第一次捕获使用宏CATCH,以后的使用AND_CATCH,而END_CATCH则用来结束异常捕获队列;

● 在异常处理程序内部,可以用THROW_LAST再次抛出最近一次捕获的异常。

标准C++的异常处理可以处理任意类型的异常,而MFC异常处理宏则只能处理CException的派生类所表示的异常,下面我们看一个文件异常类CFileException的使用例子:

        #include"afxwin.h"
        int main()
        {
            TRY
            {
              CFile f("c:\\1.txt", CFile::modeWrite );
            }
            CATCH(CFileException, e )
            {
            if( e->m_cause ==CFileException::fileNotFound )
                    AfxMessageBox("ERROR: File not found\n");
            }
            END_CATCH
        }

如果文件不存在,会提示报错。