C ++:抛出异常调用复制构造函数? [英] C++: Throwing an exception invokes the copy constructor?

查看:352
本文介绍了C ++:抛出异常调用复制构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have an custom error class that is used whenever we throw an exception:

class AFX_CLASS_EXPORT CCLAError : public CObject

它定义了以下副本构造函数:

It has the following copy constructor defined:

CCLAError(const CCLAError& src) { AssignCopy(&src); } // (AssignCopy is a custom function)

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

It was originally written and compiled / linked with MSVC6 (Visual Studio 2003). I am in the process of doing necessary changes to get it to compile and link against MSVC8+ (VS 2008+)

当msvc8链接器被调用时,我得到以下错误:

When the msvc8 linker is invoked, i get the following error:

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



我理解错误告诉我的是:没有复制构造函数是为CObject的某个子类定义的,所以它一直沿着继承树向上,直到它命中CObject,它没有定义复制构造函数。

I understand what the error is telling me: no copy constructor is defined for some child of CObject, so its going all the way up the inheritance tree until it hits CObject, which as no copy constructor defined.

我第一次看到错误当编译的库定义并首先引发一个 CCLAError ,这就是为什么我正在进行,因为这是原因。

I first saw the error when compiling the library that defines and first throws a CCLAError, which is why I am proceeding as if that is the cause.

我能够通过更改

throw CCLAError( ... )

throw new CCLAError( ... )

catch(CCLAError& e)
{
   throw e;
}

catch(CCLAError& e)
{
   throw;
}

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

However, I do not understand why re-throwing a caught exception would invoke the copy constructor. Am I missing somethnig completely obvious? Subsequently, why would removing the variable holding a reference to a caught exception cause the copy constructor to not be invoked?

推荐答案

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

The type of the object thrown must be copyable because the throw expression may make a copy of its argument (the copy may be elided or in C++11 a move may take place instead, but the copy constructor must still be accessible and callable).

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

Rethrowing the exception using throw; will not create any copies. Throwing the caught exception object using throw e; will cause a copy of e to be made. This is not the same as rethrowing the exception.

您的更新后的代码无法正常工作。 catch(CCLAError&)将不会捕获 CCLAError * 类型的异常,这是抛出的异常类型 throw new CCLAError(...); 。您需要捕获 CCLAError * 。不要这样做,虽然。通过值抛出异常并通过引用捕获异常。所有异常类型都应可复制。

Your "updated" code does not work as you expect. catch (CCLAError&) will not catch an exception of type CCLAError*, which is the type of the exception thrown by throw new CCLAError(...);. You would need to catch CCLAError*. Do not do this, though. Throw exceptions by value and catch by reference. All exception types should be copyable.

这篇关于C ++:抛出异常调用复制构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆