将以下的追加()在捕捉导致重新引发的异常看到的效果的追加()被叫什么?

try {
  mayThrowMyErr();
} catch (myErr &err) {
  err.append("Add to my message here");
  throw; // Does the rethrow exception reflect the call to append()?
}

同样,如果我改写这种方式,将位切发生,如果实际的例外是由myErr?

try {
  mayThrowObjectDerivedFromMyErr();
} catch (myErr &err) {
  err.append("Add to my message's base class here");
  throw err; // Do I lose the derived class exception and only get myErr?
}
有帮助吗?

解决方案

在这两种情况下,由于你抓住参考,你是有效改变态的原始异常的对象(其中可以认为是居住在 一个神奇的存储位置将保持有效的期间后退 -- 0x98e7058 在例如以下)。但是,

  1. 在第一种情况下,由于你重新引发与 throw; (它不同 throw err;, ,保持原来的异常对象,你的修改,在上述"神奇的地理位置"在 0x98e7058) 反映在电话追加()
  2. 在第二种情况下,由于你扔东西明确, 复制err 将创造了然后扔个新的(在一个不同的"神奇的地理位置" 0x98e70b0 -因为所有编译器知道 err 可能是一个目的堆关于被unwinded样 e0xbfbce430, 不在"神奇的地理位置"在 0x98e7058),所以 你将失去源级特定数据 在复制建设的一个基类实例。

简单的程序来说明发生了什么:

#include <stdio.h>

struct MyErr {
  MyErr() {
    printf("  Base default constructor, this=%p\n", this);
  }
  MyErr(const MyErr& other) {
    printf("  Base copy-constructor, this=%p from that=%p\n", this, &other);
  }
  virtual ~MyErr() {
    printf("  Base destructor, this=%p\n", this);
  }
};

struct MyErrDerived : public MyErr {
  MyErrDerived() {
    printf("  Derived default constructor, this=%p\n", this);
  }
  MyErrDerived(const MyErrDerived& other) {
    printf("  Derived copy-constructor, this=%p from that=%p\n", this, &other);
  }
  virtual ~MyErrDerived() {
    printf("  Derived destructor, this=%p\n", this);
  }
};

int main() {
  try {
    try {
      MyErrDerived e;
      throw e;
    } catch (MyErr& err) {
      printf("A Inner catch, &err=%p\n", &err);
      throw;
    }
  } catch (MyErr& err) {
    printf("A Outer catch, &err=%p\n", &err);
  }
  printf("---\n");
  try {
    try {
      MyErrDerived e;
      throw e;
    } catch (MyErr& err) {
      printf("B Inner catch, &err=%p\n", &err);
      throw err;
    }
  } catch (MyErr& err) {
    printf("B Outer catch, &err=%p\n", &err);
  }
  return 0;
}

结果是:

  Base default constructor, this=0xbfbce430
  Derived default constructor, this=0xbfbce430
  Base default constructor, this=0x98e7058
  Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
  Derived destructor, this=0xbfbce430
  Base destructor, this=0xbfbce430
A Inner catch, &err=0x98e7058
A Outer catch, &err=0x98e7058
  Derived destructor, this=0x98e7058
  Base destructor, this=0x98e7058
---
  Base default constructor, this=0xbfbce430
  Derived default constructor, this=0xbfbce430
  Base default constructor, this=0x98e7058
  Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
  Derived destructor, this=0xbfbce430
  Base destructor, this=0xbfbce430
B Inner catch, &err=0x98e7058
  Base copy-constructor, this=0x98e70b0 from that=0x98e7058
  Derived destructor, this=0x98e7058
  Base destructor, this=0x98e7058
B Outer catch, &err=0x98e70b0
  Base destructor, this=0x98e70b0

也参见:

其他提示

这个问题是相当的旧的和有一个答案适当的时间要求。然而,我只是想增加一个注如何做到适当的例外处理,因为 C++11 我相信这一相对应的很好你是什么努力实现与您的附加功能:

使用 std::nested_exceptionstd::throw_with_nested

它描述了在计算器 在这里,在这里,, ,你怎么可以 得到回溯上你的例外 在你的代码,而不需要一个调试器或繁琐的登录,可通过简单地写入一个适当的例外处理,这将再次引发嵌套的例外情况。

因为你可以这样做任何衍生出异常类,可以添加了很多的信息这样一种回溯!你也可以来看看我 兆瓦在。, ,其中一个回溯会看起来像这样的东西:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"

是,重新抛出重新抛出原始的异常对象,这已通过参考修改。您还可以赶上基类参考,通过将其修改,并且仍然能够通过throw;重新抛出原衍生的异常类型。

对于第一个问题,是的。

但对于第二,参照维拉德答案。 你需要仔细设计你的异常对象来处理拷贝构造函数。按照惯例,基类没有认识到它的孩子,所以你很可能会失去通过派生类中携带的附加数据。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top