함수 매개변수를 선언하는 문법과 catch 문이 거의 유사함
void f1(Widget w);
catch(Widget w) ...
매개변수와 예외는 값에 의한 전달, 참조에 의한 전달, 포인터에 의한 전달이 모두 가능
함수로의 매개변수 전달과 catch 문으로의 예외 전달의 차이점
함수를 호출했을 때는 함수를 호출한 부분으로 되돌아가지만, 예외를 발생시켰을 때에는 throw를 호출한 부분으로 되돌아가지 않음
istream operator>>(istream& s, Widget& w);
void passAndThrowWidget()
{
Widget localWidget;
cin >> localWidget;
throw localWidget;
}
localWidget이 operator>>로 전달될 때에는 참조에 의한 전달로 객체의 사본이 생성되지 않음
예외로서 발생될 때에는 값에 의한 전달이든, 참조에 의한 전달이든, 포인터에 의한 전달이든 상관 없이 객체의 사본(포인터는 포인터 객체)이 생성되어 전달됨
함수의 유효 범위를 떠난 후에는 localWidget이 소멸되기 때문에 catch문으로 전달되는 것은 쓰레기 Widget이기 때문에 사본을 만듦
(포인터에 의한 전달은 원본 객체가 소멸될 위험이 있으므로 주의)
(소멸의 위험이 없어도 사본이 생성됨)
따라서 객체의 사본을 생성하므로 속도가 느림
예외에 값에 의한 전달은 객체의 사본을 만들고 사본을 함수 매개변수에 저장하므로 두 개의 사본이 만들어짐
(함수는 한 번 복사됨)
예외 발생을 위해 객체가 복사될 때 복사 생성자는 객체의 정적 타입에 대응하는 클래스에 정의된 것이지, 동적 타입에 의해 정의된 것이 아님(다형성 지원 X)
class Widget {};
class SpecialWidget : public Widget {};
void passAndThrowWidget()
{
SpecialWidget localSpecialWidget;
Widget& rw = localSpecialWidget;
throw rw; // 예외의 타입은 Widget
}
catch (Widget& w)
{
throw;
}
catch (Widget& w)
{
throw w;
}
첫 번째 catch문은 기존 예외를 중계(rethrow)하고, 두 번째 catch문은 기존 예외의 사본을 발생
예외가 중계(rethrow)될 때에는 객체의 복사가 일어나지 않기 때문에 전달받은 타입 그대로 전달됨
예외와 catch 문에는 암시적 타입 변환 메커니즘이 적용되지 않음
void f(int value)
{
try
{
throw value;
}
catch (double d)
{
...
}
}
try 블록 안에서 발생된 int 예외는 catch 문에서 처리되지 않는데, 타입 변환이 전혀 일어나지 않기 때문에 이 catch 문은 꼭 double 타입인 것만 잡아냄
따라서 int 예외가 처리되게 하려면 int를 취하는 catch 문을 추가해야 함
그렇지만 상속 기반의 타입 변환과 타입이 있는 포인터로부터 타입이 없는 포인터(void*)로의 타입 변환은 가능
catch 문은 작성된 순서에 따라 사용됨
따라서 파생 클래스 타입을 받는 catch 문이 있다고 해도 순서가 제대로 되어 있지 않으면 기본 클래스의 타입 catch 문이 실행될 수 있음
(가상 함수를 찾는 동작 방식은 가장 적합한(best fit) 것을 선택하는 방식이고, 예외 처리 매커니즘은 첫 번째(first fit) 것을 선택하는 방식)
'C++ > More Effective C++' 카테고리의 다른 글
[More Effective C++] 항목 16 뼛속까지 잊지 말자, 80-20 법칙! (0) | 2025.03.01 |
---|---|
[More Effective C++] 항목 13 발생한 예외는 참조자로 받아내자 (0) | 2025.02.24 |
[More Effective C++] 항목 11 소멸자에서는 예외가 탈출하지 못하게 하자 (0) | 2025.02.21 |
[More Effective C++] 항목 10 생성자에서는 리소스 누수가 일어나지 않게 하자 (0) | 2025.02.20 |
[More Effective C++] 항목 9 리소스 누수를 피하는 방법의 정공은 소멸자(스마트 포인터)이다 (0) | 2025.02.19 |