본문 바로가기

Exceptional C++

(49)
항목 18 : 생성자 실패 Part2 : 흡수? 항목 17에서 객체의 생명주기와 예외의 관련성에 대해서 이야기 했다면, 이번 항목에서는 객체 생성자에서 발생된 예외는 어떻게 진행되며, 어떻게 처리 해야 좋을 지에 대한 고민을 하는 항목이다. 질문 1. 항목 17의 예제 1에서 A나 B의 생성자가 예외를 발생시키면 C의 생성자가 그 예외를 흡수해서 예외를 아예 발생하지 않게 하는 것이 가능한가? 예와 함께 왜 이런 식으로 되었는지에 대한 근거를 제시하라. 질문 2. C의 생성자(들)에 안전하게 빈 throw 정의를 넣을 수 있도록 A와 B가 지켜야 하는 최소한의 요건은 무엇인가? 해설 질문 1. 해당 질문에 답하기 위해선 표준 예외 발생에 대한 규정을 알고 있어야 할 듯 싶어, 책에서 몇가지 규칙을 설명해 준다. 1. 핸들러가 단순히 'return;' ..
Exceptional C++ 차례 반드시 읽어 볼 만한 책인것을 확신하며, 꼭 읽어보길 바란다. 번역 또한 깔끔하게 되어서, 읽는데는 문제가 없다. 이해하는것에 있어서는 기본 지식을 무척이나 많이 필요하기 때문에, .. 어리둥절하게 만드는 경우가 많으니, 비야네 책과 같이 보면 큰 도움이 될 듯 싶다. 차례 1. 일반 프로그래밍과 C++ 표준 라이브러리 항목 1 : 반복자(Iterator) 항목 2 : 대·소문자 구분 없는 문자열 - 파트 1 항목 3 : 대·소문자 구분 없는 문자열 - 파트 2 항목 4 : 최대 재사용 가능한 일반 컨테이너 - 파트 1 항목 5 : 최대 재사용 가능한 일반 컨테이너 - 파트 2 항목 6 : 임시 개체들 항목 7 : 표준 라이브러리의 사용(혹은, 다시 보는 임시 개체) 2. 예외 안전 문제와 기술들 여담 ..
항목 19 : 코드 복잡성 - 파트 2 (난이도 7) 항목 18에서 얼마나 많은 예외가 발생할 수 있는지 알아 보았다면, 이번 항목에서는 어떻게 하면 그런 예외들을 잡을 수 있을까? 에 대한 고민을 하게 해 준다. 예제 코드 string EvaluateSalaryAndReturnName( Employee e ) { if( e.Title() == "CEO" || e.Salary() > 100000 ) { cout
항목 17 : 예외에 안전한 코드를 작성하기 - 파트 10 (난이도 9/½) 지긋지긋하고 힘빠지는 예외안전성 생각하기의 막바지 항목이다. 이번 항목은 아주 중요한 질문을 던진다고 한다. C++ 표준 라이브러리가 예외에 안전한가? .... 결론부터 말하자면, 예외에 안전하다. 이것은 C++ 표준 사항에서 규정된 사항인데, 아래 규정을 보도록 하자. 표준 컨테이너에서 반환되는 모든 반복자는 예외에 안전하고 예외를 던지지도 않으며 복사 될 수 있다. 모든 표준 컨테이너는 모든 연산에 대한 기본 보증을 구현해야 하며, 항상 파괴와 예외가 있어도 견고한 상태를 유지 할 수 있어야 한다. 모든 컨테이너는 또한 반드시 모든 연산에 대해서 강한 보증을 구현해야 한다. 이것의 의미는 수행-또는-되물림(commit-or-rollback) 의 논리를 갖어야 한다는 의미이다. 성공하거나, 그 어떤 영..
항목 16 : 예외에 안전한 코드를 작성하기 - 파트 9 (난이도 8) 이전 항목(15)에서 T의 요구사항 중 한가지인 소멸자에서 예외를 발생시키지 않아야 한다고 이야기 했던것을 기억 한다면, 왜 소멸자에서 예외를 발생 시키면 안되는지에 대해서 풀어 보도록 하자. 한가지 전제를 하여 T *p = new T[10]; delete[] p; 위의 코드드 중 소멸자에서 예외가 발생 된다면, 어떤 문제점이 발생 할 수 있을까? 첫번째, 만약 생성은 모두 성공하고 delete[] 처리 중 5번째꺼에서 파괴가 된다면 어떻게 될까? 5번째부터 10번째꺼는 파괴 불가능한 상태 되는 문제가 남는다. 이것은 p[0] 가 파괴 되었기 때문에 다시 delete[] p; 를 할 수 없기 때문이다. 두번째, 만약 생성 도중 예외가 발생하여, T의 소멸자를 호출해야 할 때, 예외가 발생 한다면, 어떻게..
항목 15 : 예외에 안전한 코드를 작성하기 - 파트 8 (난이도 9) 이번 항목은 저번 13항목, 14항목에서 만들어보았던 private 기반 상속과 HAS-A 기반 관계에 대해 비교해 보는 항목이다. StackImple을 private 기반 클래스나 멤버 개체로 사용하는 것 중에 어느 기법이 더 좋은가? Stack의 두 버전은 얼마나 재사용 가능한가? 내재된 데이터형인 T의 요구사항은 무엇인가? Stack은 함수에 대한 예외 규격을 제공해야 하나? 생각해 보자. 1. private 상속이 좋은가? HAS-A 관계가 좋은가? 왜 이런 비교를 하는고 하면, 두 상속 모두 "구현 상속" 이라는 명제가 깔리기 때문이다. 클래스 기반 상속은 HAS-A 기반 관계 보다 더 관계를 맺는다.. 마치 머리에 붙은 껌 같이 강력하다. 그렇기 때문에 대부분의 사람들은 HAS-A 관계으로도 ..
항목 14 : 예외에 안전한 코드를 작성하기 - 파트 7 (난이도 5) 항목 13 에선 StackImpl 이 protected 를 나타내어 private 상속을 통하여 Stack 을 구현했다면, 이번에는 /?????/ 이 부분이 public 인터페이스일 경우, HAS-A 관계를 이용하여 Stack 을 구현해 보자. 코드 template class StackImpl { /* ? ? ? ? ? */ StackImpl( size_t size = 0 ); ~StackImpl(); void swap( StackImpl& other ) throw(); T* v_; size_t vsize_; size_t vused_; private: // private and undefined: 복사가 허용되지 않음 StackImpl( const StackImpl& ); StackImpl& operat..
항목 13 : 예외에 안전한 코드를 작성하기 - 파트 6 예제코드 template class StackImpl { /* ? ? ? ? ? */ StackImpl( size_t size = 0 ); ~StackImpl(); void swap( StackImpl& other ) throw(); T* v_; size_t vsize_; size_t vused_; private: // private and undefined: 복사가 허용되지 않음 StackImpl( const StackImpl& ); StackImpl& operator=( const StackImpl& ); }; template class Stack : private StackImpl { public: Stack( size_t size = 0 ); ~Stack(); Stack( const Stack& ..