【发布时间】:2014-04-29 09:17:53
【问题描述】:
如何捕获派生(多态)异常对象并将其重新抛出到第二级? 在我的情况下,派生对象仅保留到“级别 1”。
我了解由 c++ 编译器完成的“返回值优化”。 在我看来,在下面的代码引用中,'e' 的引用在 'Level 2' 应该不再有效,但是编译器正在隐式创建本地基类 Exception 对象,并且我失去了从 'Level 0' 抛出的原始 ExtException。
我的问题是 我怎样才能将 'ExtException' 对象保留到 'Level 2' ?
#include <string>
#include <iostream>
using std::endl;
typedef std::string pstring;
class Exception
{
public:
Exception ( ) {
my_id = ++static_count;
std:: cout << "+Exception obj created. ID: " << my_id << " (Total: " << static_count << ")" << endl;
}
Exception ( const Exception &e ) {
my_id = ++static_count;
std:: cout << "+Exception obj created. ID: " << my_id << " (Total: " << static_count << ")" << endl;
}
virtual ~Exception() {
--static_count;
std:: cout << "-Exception obj deleted. ID: " << my_id << " (Total: " << static_count << ")" << endl;
}
private:
static int static_count;
int my_id;
};
int Exception:: static_count = 0;
class ExtException : public Exception {
public:
ExtException () : Exception()
{
std:: cout << "++ExtException obj created" << endl;
}
ExtException ( const ExtException &e ) : Exception()
{
std:: cout << "++ExtException obj created" << endl;
}
~ExtException () {
std:: cout << "--ExtException obj deleted" << endl;
}
};
void foo2 () {
throw ExtException(); // Level 0 throw
}
void foo1 ()
{
try {
foo2 ();
} catch ( Exception &e ) {
// In my normal understanding of c++ 'e' should no longer be valid here
// as it was created on a stack which is no longer exists (i.e Level 0 is scoped out).
//
// _BUT_ (actually it is valid. and it is valid because of RVO compiler "Return value optimization"
std:: cout << "\n--- foo1 catch" << endl;
throw e; // Level 1 throw
}
}
void foo ()
{
try {
foo1 ();
} catch ( Exception &e ) {
// !!! CAUTION !!!
// In my opinion 'e' must not be valid here as the original "ExtException" must be destroyed till
// this point (which is actually destroyed check output trace).
// It is destroyed because RVO works for one level only...
//
// wait a minute... here the compiler has not left 'e' for FMR hit, instead it has created a new temporary object of 'Exception' class and
// 'e' is referring to that.
//
// Here comes my real question!!! 'e' is no longer referring to an actual ExtException object but the temporary one,
// how could I modify this code to access ExtException object created at 'Level 0'?
std:: cout << "\n--- foo catch" << endl;
throw e; // Level 2 throw
}
}
int main (void) {
try {
foo ();
} catch (...) { }
return 1;
}
以下是上述代码的结果:
+Exception obj created. ID: 1 (Total: 1)
++ExtException obj created
--- foo1 catch
+Exception obj created. ID: 2 (Total: 2)
--ExtException obj deleted
-Exception obj deleted. ID: 1 (Total: 1)
--- foo catch
+Exception obj created. ID: 2 (Total: 2)
-Exception obj deleted. ID: 2 (Total: 1)
-Exception obj deleted. ID: 2 (Total: 0)
【问题讨论】:
标签: c++ exception exception-handling try-catch