Exception slicing - is this due to generated copy constructor?

吃可爱长大的小学妹 提交于 2019-11-28 23:43:45

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.

A quick google suggests that yes, you're throwing the copy constructor is required and must be public. (Which makes sense, as you're initializing a copy of e and throwing that.)

Anyway, just use throw without specifying the exception object, to rethrow what was caught in the catch. Shouldn't that solve the problem?

  catch(Exception& e)
  {
    printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
    throw;
  }

Yes.

throw e;

throws an exception of the static type of e, regardless of whatever e actually is. In this case, the Derived exception is copied to an Exception using a copy constructor.

In this case you can just

throw;

to get the Derived exception bubble up correctly.

If you're interesting in polymorphical throwing in some other cases, refer to the always so useful C++ FAQ Lite.

C++ never ceases to amaze me. I would have lost a lot of money had this been a bet on what was the behaviour!

The exception object is first copied to a temporary and you should have used throw. To quote the standard 15.1/3:

A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from "array of T" or "function returning T" to "pointer to T" or "pointer to function returning T",respectively.

I think this gives rise to a very useful coding standard rule:

Base classes of an exception hierarchy should have a pure virtual destructor.

or

The copy constructor for a base class in an exception hierarchy shall be protected.

Either achieves the goal that the compiler will warn when you try to "throw e" since in the first case you cannot create an instance of an abstract class and the second because you cannot call the copy constructor.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!