HyeM

More Effective C++[항목14] 본문

Programming/C++

More Effective C++[항목14]

Hailey_HyeM207 2020. 2. 26. 19:58

항목 14 : 예외지정 기능은 냉철하게 사용하자

 

예외지정

Java처럼 그 함수가 발생시킬 예외를 미리 지정하는 기능

 

> 장점

1. 코드보기 수월

2. 예외사용을 적절히 제약해줌

 예외지정에 일관성이 없으면 컴파일러가 컴파일 도중에 발견해 줌.

 

> 단점

- 함수가 예외 지정 리스트에 없는 예외를 발생시킬 경우, 런타임 에러가 발생하면서 unexpected라는 특수함수가 자동으로 호출됨

-> 결국, 프로그램이 멈추고, 활성 스택 프레임에 만들어진 지역변수는 없어지지 않는다.

 * unexpected 함수는 terminate를 호출하여, 멈춰버린다.

- 다른 호출 측 함수에서 예외처리 코드가 준비된 상황에서조차도 unexpected가 호출될 수 있다.

 

예외 지정 불일치 피하기

방법 1.  ( 보통 타입 인자를 받아들이는 ) 템플릿에 예외지정을 두지 않는다

ㄴ템플릿에는 예외 지정을 하는 것 자체가 무 의미함. ( 템플릿을 받아들이는 타입 매개변수 많음)

ㄴ만약 아래의 소스에서 operator &가  operator== 안에서 예외를 일으키면, 예외지정약속이 어긋나며, unexpected가 호출된다.

template<class T>
bool operator==(const T& lhs, const T& rhs) throw()
{
	return &lhs == & rhs;
}

 

방법 2 .  예외 지정이 안 된 함수를 호출할 가능성을 가진 함수에는 예외 지정을 두지 않는다.

ㄴ특히 콜백함수를 등록할때 조심할 것.

// 어떤 윈도우 시스템에 이벤트가 발생했을 때, 윈도우 시스템 콜백을 위한 함수 포인터
typedef void (* CallBackPtr) (int eventXLocation, int eventYLocation, void * dataToPassBack) throw();
// 뒤에 throw() 없으면, 에러

//윈도우 시스템 개발자가 등록한 콜백함수를 담아주는 윈도우 시스템 클래스
class CallBack{
public:
	CallBack(CallBackPtr fPtr, void *dataToPassBack) : func(fPtr), data(dataToPassBack) {}
    
    void makeCallBack(int eventXLocation, int eventYLocation) const throw();
    
private:
	CallBackPtr func; //콜백이 일어날 때 호출되는 함수
    
    void * data; //콜백 함수로 넘겨지는 데이터
};

void CallBack::makeCallBack(int eventXLocation, int eventYLocation) const throw()
{
	func(eventXLocation, eventYLocation, data);
    // 위에서 throw()를 써주지 않았다면, 위에 호출되는 func는 예외 지정을 어길 위협을 안고 있음.
}

 

방법 3. '시스템'이 일으킬 가능성이 있는 예외(C++표준예외)를 처리한다.

ㄴ 이 예외 중 가장 흔한 것이 bad_alloc임 (메모리 할당에 실패한 operator new와 operator new[]가 발생시킴)

 

예기치 않은 예외를 다른 타입의 예외로 대체하는 방법

1. 

예상 밖의 예외를 객체로 대체

class UnexpectedException() ; //모든 예기치 않은 예외는 이 타입의 객체로 대체함

void convertUnexpected()
{
	throw UnexpectedException(); //예기치 않은 예외가 발생되었을 때 호출되는 함수
}

set_unexpected (convertUnexpected);
// converUnexpected가 원래의 unexpected 함수 대신 호출 되도록 함

원래의 예외지정 리스트에 UnexpectedException이 들어 있었다면, 예외 지정이 항상 만족되어 왔던 것처럼 예외전파가 꼐속됨.

 

2. 

unexpected대신에 호출되는 함수가 현재의 예외를 그대로 중계해버리면, 이 예외는 표준 타입인 bad_exception 객체로 바뀜.

void convertUnexpected()
{
	throw();
    //예기치 않은 예외가 발생할 때 호출되는 함수로, 여기서는 현재의 예외를 그대로 중계함.
}

set_unexpected(convertUnexpected);

 

'Programming > C++' 카테고리의 다른 글

More Effective C++[항목21-24]  (0) 2020.03.16
More Effective C++[항목16-20]  (0) 2020.03.10
More Effective C++[항목13]  (0) 2020.02.24
More Effective C++  (0) 2020.02.22
More Effective C++  (0) 2020.02.20
Comments