在 Visual C++ 2019 中引发自定义异常

Throwing a custom exception in Visual C++ 2019

MFC 定义了抛出预定义异常的函数。例如,您使用 ::AfxThrowFileException() 来抛出类型 CFileException 的异常。但是,如果我定义自己的异常 class,它派生自 CException 怎么办?最好的投掷方式是什么?

如果我只是这样做会不会有问题:

if (!m_Settings.IsValid())
    throw new CMyException(_T("This operation failed."));

在 Visual Studio 2019 年,上面的代码生成了以下 Intellisense 警告。但是我还没有看到任何使用 make_unique.

抛出异常的例子

Warning C26409 Avoid calling new and delete explicitly, use std::make_unique instead (r.11).

谁能解释一下,或者让我参考一些最新的文档?

异常处理是其中一个领域,它表明 MFC 在相当程度上早于 C++。由于 C++ 异常是 C++ 标准的后期添加,MFC 已经决定了它的异常处理策略:

  • 在自由存储上分配异常对象。
  • 指针抛出。
  • 指针接住。
  • 任何处理异常的 catch 子句都需要释放与异常对象关联的资源。

相比之下,处理 C++ 异常的惯用方法遵循以下准则:

  • 抛出具有按值自动存储持续时间的异常对象。
  • 按(const)参考捕获。
  • 资源清理是自动处理的。

对于 MFC,您可以使用以上任何一种。 MFC 提供了异常宏来帮助使前者更不容易出错,尽管没有严格要求使用它们中的任何一个。事实上,exception macros in version 3.0 已经开始在幕后几乎完全使用 C++ 异常处理。

在 MFC 中引发自定义异常的正确方法取决于调用它的代码。如果该代码使用 MFC 异常宏,您将需要抛出指向动态分配的异常对象的指针,例如

throw new CMyException(_T("This operation failed."));

THROW( (CException*) new CMyException(_T("This operation failed.")) );

并忽略编译器警告。这是必需的,因为 CATCH 宏将始终扩展为匹配指针类型的 catch 子句。

另一方面,如果调用代码使用 C++ 异常处理,则通过值或指针抛出都没有问题,例如

throw CMyException(_T("This operation failed."));
// or
throw new CMyException(_T("This operation failed."));

并通过 const 引用或指针捕获:

catch( CException const& ) {
    // no cleanup required
}
// or
catch( CException* e ) {
    // manual cleanup still required, unless the exception is re-thrown
    e->Delete();
}

在前面的代码片段中,还允许同时使用 catch 子句,允许您配置调用代码以处理在代码中按值抛出自定义异常以及调用 MFC 的混合情况-提供的代码引发由指针抛出的动态分配的异常对象。

在某种程度上,甚至允许混合使用 C++ 异常处理和 MFC 异常宏 (Exceptions: Using MFC Macros and C++ Exceptions)。提供信息只是为了完整性。不建议混合使用 C++ 异常和 MFC 异常宏,除非有充分的理由这样做,例如当逐渐将现有代码从 MFC 异常宏使用过渡到 C++ 异常处理时。