C++/Exception
2021. 3. 22. 00:10
예외 클래스와 상속 (Exception Class and Inheritance)
예외 클래스
예외 상황을 처리할 때 필요한 변수나 함수를 멤버로 가진 클래스
예외 클래스를 사용하지 않은 예제
#include <iostream> using namespace std; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw -1; return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (const int& x) { cerr << "Exception " << x << endl; } } int main() { doSomething(); } /* stdout stderr Exception -1 */
예외 클래스를 직접 만들어서 사용하기
#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw Exception(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { e.report(); } } int main() { doSomething(); } /* stdout stderr Exception report */
예외 클래스를 상속해서 사용하기
다형성을 적용하지 않는 경우
#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { e.report(); } } int main() { doSomething(); } /* stdout stderr Exception report */
- 객체 잘림으로 인해
Exception::report()
함수가 작동한 것을 알 수 있다.
- 객체 잘림으로 인해
다형성을 적용한 경우 (
virtual
키워드 사용)#include <iostream> using namespace std; class Exception { public: virtual void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { e.report(); } } int main() { doSomething(); } /* stdout stderr Array exception report */
맨 처음
catch
된 부분만 처리된다.#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { e.report(); } catch (ArrayException& e) { e.report(); } } int main() { doSomething(); } /* stdout stderr Exception report */
warning C4286: 'ArrayException &': is caught by base class ('Exception &') on line 44
따로 처리해야 하는 경우에는 더 작은 범위의 클래스를 위에 두면 된다.
#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (ArrayException& e) { e.report(); } catch (Exception& e) { e.report(); } } int main() { doSomething(); } /* stdout stderr Array exception report */
rethrow
catch
문 내부에서throw
를 한 번 더 사용할 경우, 값을 전달할 때 차이가 존재한다.throw e;
형태로 직접 값을 넘겨줄 경우- 객체 잘림이 발생했을 경우 잘린 상태 그대로 넘어간다.
#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { cout << "doSomething "; e.report(); throw e; } } int main() { try { doSomething(); } catch (ArrayException& e) { cout << "Main "; e.report(); } catch (Exception& e) { cout << "Main "; e.report(); } } /* stdout stderr doSomething Exception report Main Exception report */
throw;
형태로 값 없이 키워드만 작성할 경우catch
한 값을 그대로 다시throw
해서 객체 잘림이 발생하지 않는다.
#include <iostream> using namespace std; class Exception { public: void report() { cerr << "Exception report\n"; } }; class ArrayException : public Exception { public: void report() { cerr << "Array exception report\n"; } }; class MyArray { int data_[5]; public: int& operator[] (const int& index) { if (index < 0 || index >= 5) throw ArrayException(); return data_[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { cout << "doSomething "; e.report(); throw; } } int main() { try { doSomething(); } catch (ArrayException& e) { cout << "Main "; e.report(); } catch (Exception& e) { cout << "Main "; e.report(); } } /* stdout stderr doSomething Exception report Main Array exception report */
'C++ > Exception' 카테고리의 다른 글
C++ 예외 처리의 위험성과 단점 (0) | 2021.03.22 |
---|---|
C++ 함수 try (Function try) (0) | 2021.03.22 |
C++ 스택 되감기 (Stack Unwinding) (0) | 2021.03.22 |
C++ 예외 처리의 기본 (0) | 2021.03.22 |
C++ 예외 처리 (Exception Handling) (0) | 2021.03.22 |