例外(スタックに割り当てられた場合(これを強くお勧めします))は、catch句の後で解放されます。したがって、新しく作成された例外に「内部」例外のコピーを作成する必要があります。例外の基本クラスをキャッチすると、例外にcloneメソッドを指定しない限り、正しいタイプが失われます。
#include <string>
#include <exception>
class MyBaseException : public std::exception
{
public:
MyBaseException(const std::string& what = std::string("MyBaseException"))
: m_BaseException(0), m_What(what) {} //Constructor without inner exception
MyBaseException(const MyBaseException& innerException, const std::string& what = std::string("MyBaseException"))
: m_BaseException(innerException.clone()), m_What(what) {} //Constructor with inner exception
template <class T> // valid for all subclasses of std::exception
MyBaseException(const T& innerException, const std::string& what = std::string("MyBaseException"))
: m_BaseException(new T(innerException)), m_What(what) {}
virtual ~MyBaseException() throw()
{ if(m_BaseException) { delete m_BaseException; } } //don't forget to free the copy of the inner exception
const std::exception* base_exception() { return m_BaseException; }
virtual const char* what() const throw()
{ return m_What.c_str(); } //add formated output for your inner exception here
private:
const std::exception* m_BaseException;
const std::string m_What;
virtual const std::exception* clone() const
{ return new MyBaseException(); } // do what ever is necesary to copy yourselve
};
int main(int argc, char *argv[])
{
try {
try {
throw std::exception();
}
catch(const std::exception& e) {
throw MyBaseException(e, "bad");
}
}
catch (const MyBaseException& e) {
throw MyBaseException(e, "even worse");
}
//throw MyBaseException(1, "will not compile");
}