2012-04-21 6 views
5

Я использую QT 4.8 (C++) для проекта настольного приложения, и писать обработку исключений, которая выглядит следующим образом:Как избежать повторения кода в блоках catch?

void callerMethod() 
{ 
    try 
    { 
    method1(); 
    } 
    catch(Exception1& e) 
    { 
    // display critcal error message 
    // abort application 
    } 
    catch(std::Exception& e) 
    { 
    // print exception error message 
    } 
    catch(...) 
    { 
    // print unknown exception message 
    } 
} 

void method1() 
{ 
    try 
    { 
    // some initializations 
    // some operations (here exceptions can occur) 
    // clean-up code (for successful operation i.e no exception occurred) 
    } 
    catch(Exception1& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception2& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception3& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(...) 
    { 
    // clean-up code 
    throw; 
    } 
} 

Так что мой вопрос мне нужно написать очистки коды в каждом блоке поймать ? Есть ли способ я могу избежать написания повторного кода?

ПРИМЕЧАНИЕ :: [В method1()] Я хочу, чтобы повторно бросать исключения, которые произошли к моему caller.So я не могу поймать их в одном блоке поймать, потому что то типа информация будет потеряна ,

+4

Попробуйте t o уменьшить количество кода очистки, необходимого с помощью интеллектуальных указателей, классов контейнеров и т. д. В идеале не должно быть никакого кода очистки. – user763305

+0

Похоже, что вы хотите просто «try {/ * may throw * /} catch (specific_exception const & e) {/ * terminate * /}'. Если вас не интересуют типы исключений 'Exception1',' Exception2' и т. Д., То * не * ловите их. –

+1

Кроме того, даже если вы поймаете по ссылке, вы должны * реконструировать, используя 'throw;' вместо 'throw e;', чтобы предотвратить нарезку. – ereOn

ответ

8

Method1 может быть значительно упрощена путем двух понятий:

  1. RAII. Поместите любой код очистки в деструкторы, а код очистки будет централизован.
  2. Используйте неквалифицированный throw, и вам не нужно знать о типе созданного исключения.

Так, method1() должен выглядеть следующим образом:

void method1() 
{ 
    // some initializations of RAII objects 
    // some operations (here exceptions can occur) 
} 

Первый catch пункт в callerMethod может быть удален, если вы черпаете Exception1 из std::exception, так как метод what() является виртуальным.

+1

+1. Я хотел сказать это. RAII является решением здесь. – Nawaz

+0

Но я хочу обрабатывать Exception1 отдельно в callerMethod(). Если произошло Exception1, я хочу прервать приложение. – EngineeredBrain

+0

@AnwarShaikh: Вы все еще можете это сделать. RAII решает только проблему очистки. – Nawaz

0

Если все ваши очистки коды полностью идентичны, вы можете сделать все, что в вашем улове (...) блок:

try { 
    // code 
} catch (...) { 
    // cleanup 
    throw; 
} 

Если ваш код изменяется незначительно, вы всегда можете вызвать функцию очистки:

try { 
    // code 
} catch (exc1 ex) { 
    cleanup(args); 
    // exc1 specific 
    throw; 
} catch (exc2 ex) { 
    cleanup(args); 
    // exc2 specific 
    throw; 
} catch (...) { 
    cleanup(args); 
    throw; 
} 
+0

Если я пишу один catch (..), который генерирует исключение, то в методе вызывающего абонента Как я узнаю, какое исключение произошло. Потому что я хочу обработать Exception1, который прерывает приложение. – EngineeredBrain

1

Вы должны выбросить исключения как можно ниже и уловить их как можно выше в цепочке вызовов. Это автоматически приводит к меньшему дублированию кода и централизует обработку ошибок. Вы бросаете/ловите все в одном месте, что кажется немного ... принудительным.

я часто делаю такие вещи (особенно для исключения программ окончания:.

int main() 
try 
{ 
    function_calls_that_may_throw(); 
    // ... 
} 
catch(my_exception& e) 
{ 
    e.do_exception_stuff(); 
} 
catch(std::exception& e) 
{ 
    std::cout << e.what(); 
} 
catch(...) 
{ 
    std::cout << "Something bad happened.\n"; 
} 

Это возможно только для метания исключения вы не планируете обработку лучше или повторить попытку неудачной операции или что-того

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

Смежные вопросы