У меня есть следующая структура в устаревшей кодовой базе:
try{
...
}
catch(Type1&){
...
}
catch(Type2&){
...
}
...
А при разработке копирования-вставки одни и те же блоки захвата появляются везде.
Теперь я бы написал такую функцию:
void catchErrors(){
try{
throw;
}
catch(Type1&){
...
}
...
}
и вставьте его в код, например так:
try{
...
}
catch(...){
catchErrors();
}
Будет ли это действительный рефакторинг, в результате чего такая же функциональность?
(И есть ли у вас лучшее предложение для рефакторинга?)
Да, это действительно.
[C++14: 15.1/8]
: A вбрасывание выражение без операнда сбрасывает текущее обработанное исключение (15.3). Исключение повторно активируется с существующим объектом исключения; новый объект исключения не создается. Исключением не является
больше считается пойманным; следовательно, значениеstd::uncaught_exception()
снова будет правдой.[ Пример: код, который должен быть выполнен из-за исключения, но не может полностью обработать исключение, может быть написан так:
try { // ... } catch (...) { // catch all exceptions // respond (partially) to exception throw; // pass the exception to some // other handler }
— конец примера]
[C++14: 15.1/9]:
Если в настоящее время не обрабатывается ни одно исключение, выполняется выражение throw без вызовов операндовstd::terminate()
(15.5.1).
Хотя вбрасывание выражение был перемещен в свою собственную функцию, во время выполнения исключение все еще обрабатывается, поэтому оно все еще работает:
#include <iostream>
void bar()
{
try {
throw;
}
catch (int x) {
std::cerr << "Damn " << x << "!\n";
}
}
void foo()
{
try {
throw 42;
}
catch (...) {
bar();
}
}
int main()
{
foo();
}
// Output: Damn 42!
Да, ваш рефакторинг действителен. Фактически это довольно старая методика, предназначенная именно для того, чтобы переместить набор обработчиков исключений в другую функцию и разрешить их повторное использование.
Обратите внимание, что звонит ваш CatchErrors()
позвоню std::terminate()
если он вызывается вне блока обработки исключений. Это требуется от throw;
заявление, если не обрабатывается исключение.
Только не надейтесь на технику слишком сильно. Лучше проектировать большинство ваших функций с некоторыми гарантиями безопасности исключений (т. Е. Они не будут работать со сбоями, если выдается исключение, и они его не вызывают). Это дает больше возможностей для централизации обработки исключений (например, в main()
) вместо того, чтобы иметь множество различных функций, которые должны обрабатывать исключения в отдельности. Это уменьшает необходимость повторного использования кода обработки исключений, поскольку большинство исключений будет обрабатываться только в одном месте.