异常切片 - 是由于生成的复制构造函数吗? [英] Exception slicing - is this due to generated copy constructor?

查看:115
本文介绍了异常切片 - 是由于生成的复制构造函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在代码中修复了一个非常微妙的错误,这是由于异常的切片引起的,我现在想确保我明确了解发生了什么。



这是我们的基类异常类,派生类和相关函数:

 类异常
{
public:
// construction
异常(int code,const char * format =,...);
virtual〜Exception(void);

< snip - 获取/设置例程和打印功能>

protected:
private:
int mCode; // thrower设置
char mMessage [Exception :: MessageLen]; // thrower说这个FIXME:使用String
};

class Derived:public Exception {
public:
派生(const char * throwerSays):异常(1,throwerSays){};
};

void innercall {
< do stuff>
抛出(坏事发生了!);
}

void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf(Exception seen here!%s%d\\\
,__FILE__,__LINE__);
throw e;
}
}

当然,这个bug最终会抛出一个例外,而不是派生。我的错误是由于调用堆栈中的更高级别尝试捕获派生失败。



现在,我只想确保我明白 - 我相信在' 'line,正在创建一个新的Exception对象,使用默认的复制构造函数。那是真的吗?



如果是这样,我是否允许锁定将被抛出的对象的复制构造函数?我真的希望这不会再发生,我们的代码没有理由复制异常对象(我知道的)。



请不要关于事实我们有自己的异常层次结构。这是一个旧的设计,我正在努力纠正(我取得了很好的进步,我已经摆脱了本土的字符串类和许多自制的容器。)



更新:要清楚的是,在我提出问题之前,我已经修复了错误(通过更改throw e到throw)。我正在寻找确定发生了什么。

解决方案

当你抛出一个对象时,你实际上是扔一个副本的对象,不是原来的。想想一下 - 原始对象在堆栈上,但是堆栈正在被解开和无效。



我相信这是标准的一部分,但我不有一个副本参考。



在catch块中抛出的异常类型是catch的基本类型,而不是抛出的对象的类型。解决这个问题的方法是 throw; 而不是 throw e; ,这将抛出原来的捕获异常。 p>

I've just fixed a very subtle bug in our code, caused by slicing of an exception, and I now want to make sure I understand exactly what was happening.

Here's our base exception class, a derived class, and relevant functions:

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;
  }
}

The bug was of course that outercall ends up throwing an Exception, instead of a Derived. My bug resulted from higher in the call stack attempts to catch the Derived failing.

Now, I just want to make sure I understand - I believe that at the 'throw e' line, a new Exception object is being created, using a default copy constructor. Is that what's really going on?

If so, am I allowed to lock out copy constructors for objects that will be thrown? I'd really prefer this not happen again, and our code has no reason to copy Exception objects (that I know of).

Please, no comments on the fact that we have our own exception hierarchy. That's a bit of old design that I'm working to correct (I'm making good progress. I've gotten rid of the home-grown string class, and many of the home-grown containers.)

UPDATE: To be clear, I had fixed the bug (by changing 'throw e' to 'throw') before I ever asked the question. I was just looking for confirmation of what was going on.

解决方案

When you throw an object, you're actually throwing a copy of the object, not the original. Think about it - the original object is on the stack, but the stack is being unwound and invalidated.

I believe this is part of the standard, but I don't have a copy to reference.

The type of exception being thrown in the catch block is the base type of the catch, not the type of the object that was thrown. The way around this problem is to throw; rather than throw e; which will throw the original caught exception.

这篇关于异常切片 - 是由于生成的复制构造函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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