MFC TRY CATCH与C++对MFC异常的尝试捕获

MFC TRY CATCH versus C++ try catch for exceptions with MFC

本文关键字:MFC TRY CATCH C++ 异常      更新时间:2023-10-16

对于异常,我使用了正常的C++trycatch。现在我想学习如何使用MFC TRY CATCH。我尝试使用C++语法和MFC关键字抛出一个int变量,如下所示:

...
var = 0;
    TRY
    {
        if (var == 0)
        {
            THROW 5;
        }
    }
    CATCH(int a)
    {
      MessageBoxW(L"Blub", L"blub", NULL);
    }
    END_CATCH

但是它不会编译。

问题出在哪里?有人能给我解释一下吗?

或者发送一个好的链接,在那里我可以学习MFC TRY CATCH方法。我一直找不到一个好的解释。

从MSDN异常:从MFC异常宏转换

您可能不需要转换现有的代码,尽管您应该注意MFC中宏实现之间的差异3.0版本和早期版本中的实现。这些中讨论了代码行为的差异和随后的更改异常:3.0版中对异常宏的更改。委托人转换的优点是:

  • 使用C++异常处理关键字的代码编译成稍小的.EXE或.DLL.

  • C++异常处理关键字更通用:它们可以处理任何可以复制的数据类型的异常(int、float、,char等),而宏只处理类的异常CE异常及其派生的类。

宏和关键字之间的主要区别在于代码当异常超出范围。使用关键字的代码没有,所以你必须显式删除捕获的异常。有关详细信息,请参阅文章异常:捕捉和删除异常。

MFC只能捕获CException或派生类,如果要处理其他数据类型,请使用c++异常。

您提供的代码示例中存在许多源代码错误。

MFC TRY CATCH THROW不是C++关键字,而是设计用于C/C++预处理器的宏。因此,MFC宏需要使用的语法与C++关键字不同。必须使用预处理器语法。

所以你的源代码样本应该写成:

int var = 0;
TRY
    if (var == 0) {
        THROW (5);
    }
CATCH(int, a)
END_CATCH

然而,正如用户Geek在他的帖子以及对您原始帖子的评论中所说,MFC TRY CATCH THROW宏被设计为与MFC CException类一起使用,而不像C++异常那样,后者更通用,更方便。

有了上面的半校正源代码,您将看到编译器错误,如:

error C2227: left of '->IsKindOf' must point to class/struct/union/generic type
error C2039: 'GetThisClass' : is not a member of '`global namespace''
error C2146: syntax error : missing ')' before identifier 'GetThisClass'
error C2440: '=' : cannot convert from 'int *' to 'CException *'

这些错误是由于既没有使用CException类,也没有使用从CException派生的类。一般来说,MFC源库中有很多隐藏的管道,这些管道在提供相当大的功率的同时也可能受到限制。

MFC于20世纪90年代初首次发布,1998年发布了C++的第一个标准。因此,Visual Studio和MFC处于第一个C++标准化的移动目标的流血边缘。请参阅维基百科C++主题和维基百科主题Microsoft Visual C++的历史记录部分,以及VC++、MFC和ATL的版本历史记录。微软的MFC项目有着雄心勃勃的目标,即在Windows API的基础上提供一个大型而复杂的框架,以提高Windows应用程序开发人员的生产力。

通过将CATCH()中的int更改为CException,源代码现在将进行编译。

在MFC包含文件afx.h中查看,可以看到这些宏是在哪里定义的请注意,注释中说这些仅用于向后兼容性

/////////////////////////////////////////////////////////////////////////////
// Exception macros using try, catch and throw
//  (for backward compatibility to previous versions of MFC)
#define TRY { AFX_EXCEPTION_LINK _afxExceptionLink; try {
#define CATCH(class, e) } catch (class* e) 
    { ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); 
        _afxExceptionLink.m_pException = e;
#define AND_CATCH(class, e) } catch (class* e) 
    { ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); 
        _afxExceptionLink.m_pException = e;
#define END_CATCH } }
#define THROW(e) throw e
#define THROW_LAST() (AfxThrowLastCleanup(), throw)
// Advanced macros for smaller code
#define CATCH_ALL(e) } catch (CException* e) 
    { { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); 
        _afxExceptionLink.m_pException = e;
#define AND_CATCH_ALL(e) } catch (CException* e) 
    { { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); 
        _afxExceptionLink.m_pException = e;
#define END_CATCH_ALL } } }
#define END_TRY } catch (CException* e) 
    { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); 
        _afxExceptionLink.m_pException = e; } }