【发布时间】:2009-07-07 22:35:17
【问题描述】:
我刚刚在我们的代码中修复了一个由异常切片引起的非常微妙的错误,现在我想确保我完全理解发生了什么。
这是我们的异常基类、派生类和相关函数:
class Exception
{
public:
// construction
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
<snip - get/set routines and print function>
protected:
private:
int mCode; // thrower sets this
char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};
class Derived : public Exception {
public:
Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};
void innercall {
<do stuff>
throw Derived("Bad things happened!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
错误当然是外部调用最终抛出异常,而不是派生。我的错误是由于调用堆栈中较高的尝试捕获 Derived 失败造成的。
现在,我只是想确保我理解 - 我相信在“throw e”行,正在使用默认的复制构造函数创建一个新的 Exception 对象。真的是这样吗?
如果是这样,我是否可以为将被抛出的对象锁定复制构造函数?我真的不希望这种情况再次发生,而且我们的代码没有理由复制 Exception 对象(据我所知)。
请不要对我们有自己的异常层次结构这一事实提出异议。这是我正在努力纠正的一些旧设计(我正在取得良好进展。我已经摆脱了本土字符串类和许多本土容器。)
更新:需要明确的是,在我提出问题之前,我已经修复了该错误(通过将“throw e”更改为“throw”)。我只是想确认发生了什么。
【问题讨论】:
-
我知道你说过不要担心其他事情,而只是另外两件事:让你的
Exception类继承自std::exception并通过const &捕获事物。 -
捕获为 const 有什么好处?我总是通过引用来捕捉,但为什么是 const 呢? (不是说我现在可以在这门课上做到这一点,而是有一天......)
-
@Kohne:此设置中 const 的优势与任何其他设置中的类似 - 您明确指定您不打算更改对象状态的意图并且编译器应确保你不知道 - const 背后的想法是不可变对象更容易推理(即调试、测试、证明代码正确),因为它们有助于编写引用透明的代码
-
好的,这只是正常的优势。我确保没有一些微妙和特定于我不知道的异常。谢谢!
标签: c++ exception object-slicing