Как моделировать внутреннее исключение в C++

В основном я хочу моделировать Исключение.NET. InnerException в C++. Я хочу поймать исключение из нижнего слоя и перенести его за другим исключением и броском снова к верхнему уровню. Проблема здесь, я не знаю, как перенести перехваченную исключительную ситуацию в другом исключении.

struct base_exception : public std::exception
{
    std::exception& InnerException;

    base_exception() : InnerException(???) { } // <---- what to initialize with
    base_exception(std::exception& innerException) : InnerException(innerException) { }
};

struct func1_exception : public base_exception 
{
    const char* what() const throw()
    {
        return "func1 exception";
    }
};

struct func2_exception : public base_exception
{
    const char* what() const throw()
    {
        return "func2 exception";
    }
};

void func2()
{
    throw func2_exception();
}

void func1()
{
    try
    {
        func2();
    }
    catch(std::exception& e)
    {
        throw func2_exception(e); // <--- is this correct? will the temporary object will be alive?
    }
}

int main(void)
{
    try
    {
        func1();
    }
    catch(base_exception& e)
    {
        std::cout << "Got exception" << std::endl;
        std::cout << e.what();
        std::cout << "InnerException" << std::endl;
        std::cout << e.InnerException.what(); // <---- how to make sure it has inner exception ?
    }
}

В вышеупомянутом листинге кода я не уверен, как инициализировать участника "InnerException", когда нет никакого внутреннего исключения. Также я не уверен, выживет ли временный объект, который брошен от func1, даже после func2 бросок?

6
задан Sivachandran 14 May 2010 в 17:52
поделиться

4 ответа

Вам также следует взглянуть на исключение ускорения для альтернативного решения для упаковки.

3
ответ дан 17 December 2019 в 04:43
поделиться

Также я не уверен, что временный объект, который выбрасывается из временный объект, который выбрасывается из func1, сохранится даже после выполнения func2 throw?

Нет. Если только вы не перебросите исключение с помощью throw;. Вы могли бы реализовать это, если бы разрешили только некоторый (ограниченный) набор типов исключений.

1
ответ дан 17 December 2019 в 04:43
поделиться
//inversion of the problem :)
struct base_exception : public std::exception
{
    std::list<base_exception*> snowball;

    base_exception() { }
    void add(base_exception* e) { snowball.push_back(e); }
};

void func2()
{
    func2_exception e;
    e.add(new func2_exception());
    throw e;
}

void func1()
{
    try
    {
        func2();
    }
    catch(base_exception& e)
    {
        e.add(new func1_exception());
        throw e; 
    }
}
int main(void)
{
    try
    {
        func1();
    }
    catch(base_exception& e)
    {
        std::cout << "Got exception" << std::endl;
        //print info in the direct order of exceptions occurence
        foreach(base_exception* exception, e.snowball)
        {
              std::cout << exception->what();
              std::cout << "next exception was:" << std::endl;
        }
    }
}

хмммм ...

0
ответ дан 17 December 2019 в 04:43
поделиться

Одной из проблем с внутренним исключением является возможность его повторного вызова при сохранении полиморфного поведения.

Это можно (в некоторой степени) облегчить, если самостоятельно управлять временем жизни исключения и предоставлять полиморфные копии.

// Base class
class exception: virtual public std::exception, private boost::noncopyable
{
public:
  virtual exception* clone() const = 0;
  virtual void rethrow() const = 0; // throw most Derived copy
};

// ExceptionPointer
class ExceptionPointer: virtual public std::exception
{
public:
  typedef std::unique_ptr<exception> pointer;

  ExceptionPointer(): mPointer() {}
  ExceptionPointer(exception* p): mPointer(p) {}
  ExceptionPointer(pointer p): mPointer(p) {}

  exception* get() const { return mPointer.get(); }
  void throwInner() const { if (mPointer.get()) mPointer->rethrow(); }

  virtual char* what() const { return mPointer.get() ? mPointer->what() : 0; }

private:
  pointer mPointer;
};

Как использовать?

try
{
  // some code
}
catch(exception& e)
{
  throw ExceptionPointer(e.clone());
}

// later on
try
{
}
catch(ExceptionPointer& e)
{
  e.throwInner();
}
0
ответ дан 17 December 2019 в 04:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: