MFC TRY CATCH 与 C++ 尝试使用 MFC 捕获异常

Posted

技术标签:

【中文标题】MFC TRY CATCH 与 C++ 尝试使用 MFC 捕获异常【英文标题】:MFC TRY CATCH versus C++ try catch for exceptions with MFC 【发布时间】:2014-11-09 14:58:31 【问题描述】:

我使用普通的 C++ trycatch 处理异常。现在我想学习如何使用 MFC TRY CATCH。我尝试使用带有 MFC 关键字的 C++ 语法抛出 int 变量,如下所示:

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

但是它没有编译。

问题出在哪里?谁能给我解释一下?

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

【问题讨论】:

使用 MFC 宏只能捕获 CException*。该宏已经过时了,不要使用它。 Here 是微软建议将 MFC 宏转换为普通 c++ try/catch 的页面。 【参考方案1】:

来自 MSDN Exceptions: Converting from MFC Exception Macros

您可能不需要转换现有代码,尽管您应该 注意 MFC 中宏实现之间的差异 3.0 版和早期版本中的实现。这些 代码行为的差异和后续变化在 Exceptions: Changes to Exception Macros in Version 3.0。校长 转换的优点是:

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

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

宏和关键字的主要区别在于代码 使用宏“自动”删除捕获的异常时 异常超出范围。使用关键字的代码没有,所以你 必须显式删除捕获的异常。有关详细信息,请参阅 文章Exceptions: Catching and Deleting Exceptions。

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

【讨论】:

【参考方案2】:

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

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

所以你的源代码示例应该写成:

int var = 0;

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

但是,作为上面的用户 Geek 以及您原始帖子的 cmets,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 于 1990 年代初在 1998 年发布第一个 C++ 标准之前首次发布。因此,Visual Studio 和 MFC 处于第一个 C++ 标准化的移动目标的最前沿。请参阅 History section of the Wikipedia C++ topic 和 Wikipedia topic Microsoft Visual C++ 以及 Version history of VC++, MFC and ATL。 Microsoft 的 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;  

【讨论】:

以上是关于MFC TRY CATCH 与 C++ 尝试使用 MFC 捕获异常的主要内容,如果未能解决你的问题,请参考以下文章

try/catch 和 MFC TRY/CATCH 有啥区别?

C++ try-catch语法分析与应用

在 C++ 和 C# 中使用 try/catch 的正确方法是啥? [复制]

C++异常如何写

C++异常如何写

C++,__try 和 try/catch/finally