Используя броска;` на основе модифицированной исключение



у меня есть функция foo что может бросить bar исключения.



в другой функции я называю foo но у меня есть возможность добавить еще несколько деталей к bar исключение, если бросили. (Я бы предпочел не передавать такую информацию в качестве параметра foo поскольку он действительно не принадлежит там из-за общей природы этой функции.)



поэтому я делаю это в вызывающем абоненте:



try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}


будет throw повторно бросить измененное исключение или мне нужно использовать throw ex;? Последний, по-видимому, возьмет копию значения, поэтому я бы предпочел этого не делать. Хотел бы throw возьмите копию значения тоже? Я подозреваю, что это не.



(Я знаю, что могу проверить, но я беспокоюсь о том, чтобы наткнуться на неопределенную или неопределенную конструкцию, поэтому хотел бы знать наверняка).

662   5  

5 ответов:

C++11 §15.1 / 8:

" A throw-expression без операнда перестраивает обрабатываемое в данный момент исключение (15.3). Исключение составляет повторная активация с помощью существующего временного объекта; новый объект временного исключения не создается.

на самом деле, стандарт здесь очень точен. [кроме.handle] / 17:

когда обработчик объявляет ссылку на непостоянный объект,любой изменения объекта ссылки - это изменения временного объекта инициализируется, когда throw-expression был выполнен и будет иметь эффект, если этот объект будет переосмыслен.

и [за исключением.throw] / 8:

A throw-expression С ни один операнд не переосмысливает обрабатываемый в данный момент исключение (15.3).

в этом случае вы должны использовать throw чтобы получить желаемое поведение...т. е. throw будет бросать измененное исключение, поскольку исключение было поймано ссылкой.

позвольте мне попытаться сделать разницу между этими явными примерами броска: -

class exception
{
};

class MyException : public exception
{
};

void func()
{
  try
  {
    throw MyException();
  }
  catch( exception& e )
  {
    //do some modification.
    throw;                    //Statement_1
    throw e;                  //Statement_2
   }
}

Statment_1: -

что бросок делает это просто повторно бросает то, что текущее исключение, т. е. он не делает дальнейших копий ( как было сделано, когда исключение было брошено изначально). Так что если вы сделаете какие-либо изменения к пойманному исключению here...it также будет там в подпрограмме вызывающего абонента.

Statement_2: -

это бросает "исключение", которое первоначально было поймано как MyException, т. е. оно снова сделает копию. Итак, просто забудьте об изменениях, которые вы сделали, это даже не пройдет или * ginal исключение для вызывающего абонента. Он выдает" исключение " для вызывающей процедуры.

надеюсь, что я ясно (и прямо на пути стандарта C++) достаточно...

throw (без объекта исключения) будет повторно создать текущее исключение. (должно быть внутри блока catch, иначе std:: terminate называется). Поскольку вы изменили ссылку на текущий объект исключения, вам не нужно явно бросать объект и бросить повторно бросить измененное исключение и новый временный объект не создается.

по данным этой, выбрасывание исключений в c++ может быть сделано двумя способами:

  1. броситьвыражение: во-первых, copy-инициализирует объект исключения из выражения (это может вызвать конструктор перемещения для выражения rvalue, а копирование / перемещение может подлежать копированию elision), затем передает управление обработчику исключений с соответствующим типом, чей составной оператор или список инициализаторов членов был введен последним и не выходит из этого потока выполнения.
  2. бросить: повторно создает обрабатываемое в данный момент исключение. Отказывается от выполнения текущего блока catch и передает управление следующему соответствующему обработчику исключений (но не другому предложению catch после того же блока try: его составной оператор считается "завершенным"), повторно используя существующий объект исключения: новые объекты не создаются. Эта форма разрешена только тогда, когда в настоящее время обрабатывается исключение (оно вызывает с std::прекратить, если используется иное). Предложение catch, связанное с блоком function-try-block, должно выйти через повторное расширение, если оно используется в конструкторе.

так, чтобы подчеркнуть мой ответ, бросить должно быть хорошо в вашем случае.

Comments

    Ничего не найдено.