C++:抛出异常会调用复制构造函数吗?

joh*_*tke 1 c++ exception visual-c++

我们有一个自定义错误类,每当我们抛出异常时都会使用它:

class AFX_CLASS_EXPORT CCLAError : public CObject
Run Code Online (Sandbox Code Playgroud)

它定义了以下复制构造函数:

CCLAError(const CCLAError& src) { AssignCopy(&src); } // (AssignCopy is a custom function)
Run Code Online (Sandbox Code Playgroud)

它最初是用MSVC6(Visual Studio 2003)编写和编译/链接的.我正在进行必要的更改以使其编译并链接到MSVC8 +(VS 2008+)

调用msvc8链接器时,我收到以下错误:

LNK2001: unresolved external symbol "private: __thiscall CObject::CObject(class CObject const &)" (??0CObject@@AAE@ABV0@@Z)
Run Code Online (Sandbox Code Playgroud)

我理解错误告诉我的内容:没有为CObject的某个子节点定义复制构造函数,所以它一直向上继承树,直到它到达CObject,因为没有定义复制构造函数.

我在编译定义并首先抛出a的库时首先看到了错误CCLAError,这就是为什么我继续进行,就好像这是原因.

我能够通过改变来解决错误

throw CCLAError( ... )
Run Code Online (Sandbox Code Playgroud)

throw new CCLAError( ... )
Run Code Online (Sandbox Code Playgroud)

catch(CCLAError& e)
{
   throw e;
}
Run Code Online (Sandbox Code Playgroud)

catch(CCLAError& e)
{
   throw;
}
Run Code Online (Sandbox Code Playgroud)

但是,我不明白为什么重新抛出一个被捕获的异常会调用复制构造函数.我错过了一些完全明显的东西吗?随后,为什么删除持有对捕获的异常的引用的变量会导致不调用复制构造函数?

Jam*_*lis 9

抛出的对象的类型必须是可复制的,因为throw表达式可以复制其参数(复制可能被省略,或者在C++ 11中可能会发生移动,但复制构造函数仍然必须是可访问和可调用的).

重新使用异常throw;将不会创建任何副本.使用捕获的异常对象throw e;将导致生成副本e.这与重新抛出异常不同.

您的"更新"代码无法按预期工作. catch (CCLAError&)不会捕获类型的异常CCLAError*,这是抛出的异常的类型throw new CCLAError(...);.你需要抓住CCLAError*.但是,不要这样做.按值抛出异常并通过引用捕获.所有异常类型都应该是可复制的.


K-b*_*llo 5

但是,我不明白为什么重新抛出一个被捕获的异常会调用复制构造函数.

它没有,但重新抛出抛出的异常就完成了throw;.当您这样做时,throw e;您要求抛出捕获的异常的副本.