Используя броска;` на основе модифицированной исключение
у меня есть функция foo что может бросить bar исключения.
в другой функции я называю foo но у меня есть возможность добавить еще несколько деталей к bar исключение, если бросили. (Я бы предпочел не передавать такую информацию в качестве параметра foo поскольку он действительно не принадлежит там из-за общей природы этой функции.)
поэтому я делаю это в вызывающем абоненте:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
будет throw повторно бросить измененное исключение или мне нужно использовать throw ex;? Последний, по-видимому, возьмет копию значения, поэтому я бы предпочел этого не делать. Хотел бы throw возьмите копию значения тоже? Я подозреваю, что это не.
(Я знаю, что могу проверить, но я беспокоюсь о том, чтобы наткнуться на неопределенную или неопределенную конструкцию, поэтому хотел бы знать наверняка).
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++ может быть сделано двумя способами:
- броситьвыражение: во-первых, copy-инициализирует объект исключения из выражения (это может вызвать конструктор перемещения для выражения rvalue, а копирование / перемещение может подлежать копированию elision), затем передает управление обработчику исключений с соответствующим типом, чей составной оператор или список инициализаторов членов был введен последним и не выходит из этого потока выполнения.
- бросить: повторно создает обрабатываемое в данный момент исключение. Отказывается от выполнения текущего блока catch и передает управление следующему соответствующему обработчику исключений (но не другому предложению catch после того же блока try: его составной оператор считается "завершенным"), повторно используя существующий объект исключения: новые объекты не создаются. Эта форма разрешена только тогда, когда в настоящее время обрабатывается исключение (оно вызывает с std::прекратить, если используется иное). Предложение catch, связанное с блоком function-try-block, должно выйти через повторное расширение, если оно используется в конструкторе.
так, чтобы подчеркнуть мой ответ, бросить должно быть хорошо в вашем случае.
Comments