Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 10 лет назад пользователемНаталия Твардовская
2 Исключения как механизм обработки ошибок Варианты обработки ошибок без исключений: 1.Умолчание ошибки int atoi ( const char * str ); const char * strVal = abc; … const int val = atoi(strVal); // результат функции 0 2. Возвратить результат операции bool strToInt(const char * str, int & out); const char * strVal = abc; … int val = 0; strToInt(strVal, val); // Результат операции не проверяется
3 3. Выставить глобальный флаг ошибки int errorFlag; #define ERR_NO_ERROR #define ERR_INCORRECT_INPUT … int strToInt(const char * str) { errorFlag = ERR_NO_ERROR; … errorFlag = ERR_INCORRECT_INPUT; return 0; … } int main() { … const int val = strToInt (strVal); // функция вернет 0 If (errorFlag != ERR_NO_ERROR) { … } … }
4 Базовый синтаксис try..catch…throw try { throw T1(); … throw T2(); … throw T3(); } catch(T1 t1) { … } catch(T2 t2) { … } catch (…) // все типы исключений { }
5 class InputError { … }; int strToInt(const char * str) { … throw InputError(); … } int main() { … try { …. const int value = strToInt(strValue); … } catch(InputError error) { std::cout
6 Исключение – это один из способов передачи управления int fun() { … return 0; … } int fun() { … throw std::runtime_error(); … } int fun2() { … fun(); … } try { fun2(); } catch(std::runtime_error & err) { }
7 Особенности обработчика catch try { throw E(); } catch(H) { … } Обработчик catch (H) будет вызван, если: 1.Если Н того же типа что и Е; 2.Если Н является открытой базой Е; 3.Будет выполнено для указателей и ссылок если выполняется [1] или [2];
8 Особенности обработчика catch try { throw 4; // выбросили исключение типа int } catch(int errNum) // попали в обработчик исключения типа int { … } Обработчик catch (H) будет вызван, если: 1.Если Н того же типа что и Е 2.Если Н является открытой базой Е 3.Будет выполнено для указателей и ссылок если выполняется [1] или [2]
9 Особенности обработчика catch try { throw std::runtime_error; } catch(std::exception err) { … } Обработчик catch (H) будет вызван, если: 1.Если Н того же типа что и Е 2.Если Н является открытой базой Е 3.Будет выполнено для указателей и ссылок если выполняется [1] или [2] std::exception std::runtime_error
10 Перехват всех исключений и повторная генерация try { … } catch(…) // перехватить все типы исключений { … throw; //выброcить еще раз то же самое исключение … }
11 Порядок следования catch - секций try { } catch (int numErr) { … } catch (std::exception exc) {... } catch(std::runtime_error exc) {... } std::exception std::runtime_error
12 Порядок следования catch - секций try { throw std::runtime_error (); } catch(std::runtime_error exc) // сработает { } catch (std::exception exc) { } catch(…) { } std::exception std::runtime_error
13 Иерархия классов исключений и секция catch try { throw SpecialException(); } catch (BaseException exc) { cout
14 Иерархия классов исключений и секция catch try { throw SpecialException(); } catch (const BaseException & exc) { cout
15 Принцип RAII и исключения RAII - Resource Acquisition Is Initialization
16 bool fun() { … Dictionary * dict = new Dictionary(); If (!dict->loadDictionary(path)) { delete dict; return false; } EncodingConverter * converter = new EncodingConverter (); If (!converter->init()) { delete dict; delete converter ; return false; } OperationController *controller = new OperationController(dict, converter); If (!controller->init()) { delete dict; delete converter ; delete controller ; return false; } // некоторые действия и также вызов освобождение dict, converter, controller }
17 void fun() { // захватить ресурс 1 // захватить ресурс 2 … // захватить ресурс N // использование ресурсов // освободить ресурс 1 // освободить ресурс 2 … // освободить ресурс N }
18 Решение 1 bool fun() { … Dictionary * dict = new Dictionary(); EncodingConverter * converter = new EncodingConverter (); OperationController controller = new OperationController(dict, converter); try { If (!dict->loadDictionary(path)) throw DictionaryInitError(); … } catch(…) { delete dict; delete converter ; delete controller ; return false; } delete dict; … return true; }
19 Решение 2 class AutoDictionary { public: AutoDictionary(Dictionary * dict) : mDict(dict) { } ~AutoDictionary() { delete mDict;} Dictionary *operator->() { return mDict; } private: Dictionary * mDict; };
20 Решение 2 void fun() { … AutoDictionary dict(new Dictionary()); AutoEncodingConverter converter(new EncodingConverter ()); AutoOperationController controller (new OperationController(dict.get(), converter.get())); if (!dict->loadDictionary(path)) throw DictionaryInitError(); if (!converter->init()) throw ConverterInitError(); if (!controller->init()) throw ControllerinitError(); … }
21 Решение 3 void fun() { … std::auto_ptr dict(new Dictionary()); std::auto_ptr converter(new EncodingConverter ()); std::auto_ptr controller (new OperationController(dict.get(), converter.get())); If (!dict->loadDictionary(path)) throw DictionaryInitError(); If (!converter->init()) throw ConverterInitError(); If (If (!controller->init()) throw ControllerinitError(); … }
22 bool fun() { … std::auto_ptr dict(new Dictionary()); std::auto_ptr converter(new EncodingConverter ()); std::auto_ptr controller (new OperationController(dict.get(), converter.get())); if (!dict->loadDictionary(path)) return false; if (!converter->init()) return false; if (!controller->init()) return false; … }
23 преобразования типов void fun(double val); … fun(1); // будет вызвана fun(double val); fun(1.0); … try { throw 1; //генерация int - исключения } catch(double) // обработчик для double типа { … // не сработает для int } Допускается для: 1.Для наследуемых типов; 2.Из типизированного в нетипизированный указатель (void * ); try { throw Error; // тип cont char * throw new std::runtime_error(); // тип std::runtime_error * } catch(void * ptr) // перехватить все исключения типа указатель { … }
24 Неперехваченные исключения int main() { throw 4; } int main() { try { … } catch(…) { … } std::terminate() -> abort()
25 Спецификация исключений на уровне определения функций void fun() throw (x1, x2); void fun() throw (std::runtime_error, int); void fun() { try { } catch (std::runtime_error) { throw; } catch (int) { throw; } catch(…) { std::unexpected(); } std::unexpected() - >std::terminate() -> abort()
26 void f(); // может генерировать любое исключение void f() throw(); // не генерирует исключений void f() throw(std::exception, int); // генерирует исключения типа int, std::exception и // производные от std::exception void fun() throw() { throw 1; } int main() { fun(); return 0; }
27 class A { public: virtual ~A() { } virtual void f(); virtual void g() throw(X, Y); virtual void h() throw(X); }; class B : public A { public: virtual void f() throw(X); virtual void g() throw(X); virtual void h() throw(X, Y); };
28 Неожиданные исключения и std::bad_exception 1. std:: bad_exception void f() throw(X, std::bad_exception) { … throw 1; //выбрасываем исключение типа int (будет выброшено std::bad_exception) … } 2. unexpected_handler typedef void(*unexpected_handler); unexpected_handler set_unexpected(unexpected_handler) throw( );
29 Исключения в конструкторах Без использования исключений: 1.Сконструировать объект с некорректным состоянием class A { public: A(); bool isValidConstructed() const; }; … A a; If (!a. isValidConstructed()) { … } …
30 2. Присвоить значение глобальной переменной; 3. Не делать инициализации в конструкторе и сделать отдельную функцию инициализации. class A { public: A() {} bool init(); };
31 4.Пометить объект как неинициализированный и во всех функциях проверять состояние объекта; … const int gErrCodeInitError=-2; … class A { public: A() { … mInitialized = false; … } int fun() { If (! mInitialized ) return gErrCodeInitError; … } private: bool mInitialized; };
32 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) : mConnection(NULL) { mConnection = new db::DBConnection(); std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } … private: db::DBConnection * mConnection; }; try { DBConnectionWrapper dbConnectionWrapper (username, psw); … } catch(DBConnectionFailed & exc) …
33 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) : mConnection(NULL) { mConnection = new db::DBConnection(); std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } ~ DBConnectionWrapper() { delete mConnection; // Не сработает, если в конструкторе было исключение } … private: db::DBConnection *mConnection; }; Удаляются только полностью сконструированные объекты!!!
34 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) : mConnection(NULL) { try { mConnection = new db::DBConnection(); std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } catch(…) { delete mConnection ; throw; } … private: db::DBConnection *mConnection; };
35 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) try : mConnection(NULL) { mConnection = new db::DBConnection(); std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } catch(…) { delete mConnection ; throw; } … private: db::DBConnection *mConnection; };
36 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) : mConnection(new db::DBConnection()) { std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } … private: AutoConnection mConnection; }; AutoConnection { public: AutoConnection(db::DBConnection *connection) : mConnection(connection) { } ~AutoConnection() { delete mConnection; } db::DBConnection * operator->() { return mConnection; } private: db::DBConnection * mConnection; };
37 Использование smart pointer class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw) : mConnection(new db::DBConnection()) { std::string error; if (mConnection->connect(username, psw, error)) throw DBConnectionFailed(error); } … private: std::auto_ptr mConnection; };
38 Исключения в деструкторах class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw); ~DBConnectionWrapper() { mConnection->close(error); // может быть сгенерировано исключение } private: std::auto_ptr mConnection; }; Деструктор объекта вызывается в следующих случаях: 1.Выход из области видимости или оператор delete; 2.В процессе обработки исключения: в процессе раскручивания стека;
39 Деструктор объекта вызывается в следующих случаях: 1.Выход из области видимости или оператор delete; 2.В процессе обработки исключения: в процессе раскручивания стека; void makeQuery(std::string sql) { … DBConnectionWrapper connection(username, psw); … If (!connection.query(sql)) throw QueryFailed(); // автоматически будет вызван ~DBConnectionWrapper … }
40 class DBConnectionWrapper { public: DBConnectionWrapper(const std:string & username, const std::string & psw); ~DBConnectionWrapper() { try { mConnection->close(error); // может быть сгенерировано исключение } catch(…) { } private: std::auto_ptr mConnection; };
41 Стандартные исключения exception logic_errorruntime_error length_error domain_error out_of_range invalid_argument bad_alloc bad_exception io_base::failure bad_typeid bad_cast range_error overflow_error underflow_error
42 1. std::bad_alloc SomeClass sc = new SomeClass(); // может быть сгенерировано исключение std::bad_alloc 2. std::bad_cast B & b = dynamic_cast (a); // может быть сгенерировано исключение std::bad_cast 3. std::bad_exception Для спецификации исключений
43 Гарантия безопасности исключений Уровни гарантий: 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety;
44 class Node { int mData; Node * mPNext; } class IntList { public: … void add(int value) { mCachedSize ++; Node * node = new Node(); // возможно исключение std::bad_alloc … } … Unsigned int size() const { return mCachedSize; } private: … unsigned int mCachedSize; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety;
45 class Node { int mData; Node * mPNext; } class IntList { public: … void add(int value) throw (std::bad_alloc) { mCachedSize ++; // некорректное значение размера Node * node = new Node(); // возможно исключение std::bad_alloc … } … Unsigned int size() const { return mCachedSize; } private: … unsigned int mCachedSize; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety;
46 class Node { int mData; Node * mPNext; } class IntList { public: … void add(int value) throw (std::bad_alloc) { Node * node = new Node(); // возможно исключение std::bad_alloc … mCachedSize ++; // Увеличить размер только после полностью завершенной // операции } … Unsigned int size() const { return mCachedSize; } private: … unsigned int mCachedSize; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety;
47 class T1; class T2; class A { public: … A & operator=(const A & obj) { mT1 = obj.mT1; mT2 = obj.mT2; return *this; } … private: T1 mT1; T2 mT2; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety; Гарантия безопасности и operator=
48 class T1; class T2; class A { public: … A & operator=(const A & obj) { mT1 = obj.mT1; mT2 = obj.mT2; // может произойти исключение return *this; } … private: T1 mT1; T2 mT2; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety; Гарантия безопасности и operator=
49 class A { public: … A & operator=(const A & obj) { A tmp(obj); swap(tmp); return *this; } … private: void swap(A & a) throw(); T1 mT1; T2 mT2; }; 1. no throw guarantee; 2. strong exception safety (commit or rollback semantics); 3. basic exception safety; 4. Minimal exception safety; 5. No exception safety; Гарантия безопасности и operator=
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.