Chapter 15. 예외처리(Exception Handling) 윤성우의 열혈 C++ 프로그래밍 윤성우 저 열혈강의 C++ 프로그래밍 개정판 Chapter 15. 예외처리(Exception Handling)
Chapter 15-1. 예외상황과 예외처리의 이해 윤성우의 열혈 C++ 프로그래밍 Chapter 15-1. 예외상황과 예외처리의 이해 윤성우 저 열혈강의 C++ 프로그래밍 개정판
예외상황을 처리하지 않았을 때의 결과 윤성우의 열혈 C++ 프로그래밍 실행결과1 실행결과2 √ 예외상황은 프로그램 실행 중에 발생하는 문제의 상황을 의미한다. √ 예외상황의 예 나이를 입력하라고 했는데, 0보다 작은 값이 입력됨. 나눗셈을 위해서 두 개의 숫자를 입력 받았는데, 제수로 0이 입력됨. 주민등록번호 13자리만 입력하라고 했는데 중간에 –가 삽입됨. √ 이렇듯 예외는 문법적 오류가 아닌, 프로그램 논리에 맞지 않는 오류를 뜻한다. 실행결과1 실행결과2
if문을 이용한 예외의 처리 윤성우의 열혈 C++ 프로그래밍 실행결과 num2에 0이 입력됨으로 인해서 예외가 발생 if문 안에서 예외를 처리! 실행결과
Chapter 15-2. C++의 예외처리 메커니즘 윤성우의 열혈 C++ 프로그래밍 Chapter 15-2. C++의 예외처리 메커니즘 윤성우 저 열혈강의 C++ 프로그래밍 개정판
C++의 예외처리 메커니즘 이해: try, catch, throw 윤성우의 열혈 C++ 프로그래밍 √ try 블록은 예외발생에 대한 검사범위를 지정하는데 사용된다. √ catch 블록은 try 블록에서 발생한 예외를 처리하는 영역으로 그 형태가 마차 반환형 없는 함수와 같다. √ throw는 예외의 발생을 알리는 역할을 한다. √ try~catch는 하나의 문장이므로 그 사이에 다른 문장이 삽입될 수 없다.
예외처리 메커니즘의 적용 윤성우의 열혈 C++ 프로그래밍 실행결과1 실행결과2 예외의 발생으로 인해서 try 블록 내에서 throw절이 실행이 되면, try 블록의 나머지 부분은 실행이 되지 않는다! 실행의 흐름을 이해하는 것이 중요! 실행의 흐름은 try 블록 안으로 들어간다. 그 안에서 예외가 발생하면 이후에 등장하는 catch 블록을 실행하게 된다. 예외가 발생하지 않으면 try 블록을 빠져 나와 try~ catch 블록 이후를 실행하게 된다.
try 블록을 묶는 기준 윤성우의 열혈 C++ 프로그래밍 예외와 연관이 있는 부분을 모두 하나의 try 블록으로 묶어야 한다! 잘 묶인 예! 잘못 묶인 예! 예외와 연관이 있는 부분을 모두 하나의 try 블록으로 묶어야 한다!
Chapter 15-3. Stack Unwinding(스택 풀기) 윤성우의 열혈 C++ 프로그래밍 Chapter 15-3. Stack Unwinding(스택 풀기) 윤성우 저 열혈강의 C++ 프로그래밍 개정판
예외의 전달 윤성우의 열혈 C++ 프로그래밍 예외가 Divide 함수 내에서 발생한다! 그런데 발생한 지점을(throws 절을) 감싸는 try 블록이 존재하지 않는다! 예외가 처리되지 않으면, 예외가 발생한 함수를 호출한 영역으로 예외 데이터가(더불어 예외처리에 대한 책임까지) 전달된다
예외의 발생위치와 처리위치가 달라야 하는 경우 윤성우의 열혈 C++ 프로그래밍 함수의 비정상 종료에 따른 처리를 main 함수에서 해야 하므로 예외의 처리는 main 함수에서 진행되어야 한다. 예외의 데이터가 전달되면, 함수는 더 이상 실행되지 않고 종료된다. 실행결과
스택 풀기(Stack Unwinding) 윤성우의 열혈 C++ 프로그래밍 main 함수에서조차 예외를 처리하지 않으면, terminate 함수(프로그램을 종료시키는 함수)가 호출되면서 프로그램이 종료됨.
자료형이 일치하지 않아도 예외 데이터는 전달 윤성우의 열혈 C++ 프로그래밍 형 변환 발생하지 않아서 예외 데이터는 SimpleFunc 함수를 호출한 영역으로 전달된다.
하나의 try 블록과 다수의 catch 블록 윤성우의 열혈 C++ 프로그래밍 하나의 try 영역 내에서 종류가 다른 둘 이상의 예외가 발생할 수 있기 때문에, 하나의 try 블록에 다수의 catch 블록을 추가할 수 있다.
전달되는 예외의 명시 윤성우의 열혈 C++ 프로그래밍 함수 내에서 예외상황의 발생으로 인해서 int형 예외 데이터와 char형 예외 데이터가 전달될 수 있음을 명시한 선언 따라서 이 함수를 호출하는 영역의 코드는 다음과 같이 구성해야 한다. int, char 이외의 예외 데이터가 전달되면, terminate 함수의 호출로 인해서 프로그램이 종료된다. 프로그램의 종료는 대비하지 못한 예외상황의 처리를 알리는 의미로 받아들여진다. 어떠한 예외가 발생해도 프로그램은 종료가 된다! 이 함수는 어떠한 예외상황도 발생하지 않는다는 의미의 함수 선언!
Chapter 15-4. 예외상황을 표현하는 예외 클래스의 설계 윤성우의 열혈 C++ 프로그래밍 Chapter 15-4. 예외상황을 표현하는 예외 클래스의 설계 윤성우 저 열혈강의 C++ 프로그래밍 개정판
예외 클래스와 예외객체 윤성우의 열혈 C++ 프로그래밍 √ 예외객체 : 예외발생을 알리는데 사용되는 객체 √ 예외객체 : 예외발생을 알리는데 사용되는 객체 √ 예외 클래스 : 예외객체의 생성을 위해 정의된 클래스 √ 객체를 이용해서 예외상황을 알리면 예외가 발생한 원인에 대한 정보를 보다 자세히 담을 수 있다. class DepositException { private: int reqDep; // 요청 입금액 public: DepositException(int money) : reqDep(money) { } void ShowExceptionReason() { cout<<"[예외 메시지: "<<reqDep<<"는 입금불가]"<<endl; } }; class WithdrawException int balance; // 잔고 WithdrawException(int money) : balance(money) { } cout<<"[예외 메시지: 잔액 "<<balance<<", 잔액부족]"<<endl; } 입금 관련 예외상황의 표현을 위해서 정의된 클래스 예외 클래스 출금 관련 예외상황의 표현을 위해서 정의된 클래스 예외 클래스
예외 클래스 기반의 예외처리 윤성우의 열혈 C++ 프로그래밍 객체 형태의 예외 데이터 예외객체의 멤버함수 호출 class Account { private: char accNum[50]; // 계좌번호 int balance; // 잔고 public: Account(char * acc, int money) : balance(money) { strcpy(accNum, acc); } void Deposit(int money) throw (DepositException) { if(money<0) { DepositException expn(money); throw expn; } balance+=money; void Withdraw(int money) throw (WithdrawException) if(money>balance) throw WithdrawException(balance); balance-=money; void ShowMyMoney() cout<<"잔고: "<<balance<<endl<<endl; }; int main(void) { Account myAcc("56789-827120", 5000); try myAcc.Deposit(2000); myAcc.Deposit(-300); } catch(DepositException &expn) expn.ShowExceptionReason(); myAcc.ShowMyMoney(); myAcc.Withdraw(3500); myAcc.Withdraw(4500); catch(WithdrawException &expn) return 0; 객체 형태의 예외 데이터 예외객체의 멤버함수 호출 임시객체의 형태로 전달 가능! 예외객체의 멤버함수 호출
상속관계에 있는 예외 클래스 윤성우의 열혈 C++ 프로그래밍 class AccountException { public: try virtual void ShowExceptionReason()=0; }; try { myAcc.Deposit(2000); myAcc.Deposit(-300); } catch(AccountException &expn) expn.ShowExceptionReason(); myAcc.Withdraw(3500); myAcc.Withdraw(4500); class DepositException : public AccountException { private: int reqDep; public: DepositException(int money) : reqDep(money) { } void ShowExceptionReason() cout<<"[예외 메시지: "<<reqDep<<"는 입금불가]"<<endl; } }; class WithdrawException : public AccountException int balance; WithdrawException(int money) : balance(money) cout<<"[예외 메시지: 잔액 "<<balance<<", 잔액부족]"<<endl; Depos~ 예외 클래스와 With~ 예외 클래스는 AccountException 클래스를 상속하므로 AccountException을 대상으로 정의된 catch 블록에 의해 처리될 수 있다.
예외의 전달방식에 따른 주의사항 윤성우의 열혈 C++ 프로그래밍 맨 위에 있는 catch 블록부터 시작해서 아래로 적절한 catch 블록을 찾아 내려온다 예외객체의 전달과정에서의 문제점은?
Chapter 15-5. 예외처리와 관련된 또 다른 특성들 윤성우의 열혈 C++ 프로그래밍 Chapter 15-5. 예외처리와 관련된 또 다른 특성들 윤성우 저 열혈강의 C++ 프로그래밍 개정판
new 연산자에 의해서 전달되는 예외 윤성우의 열혈 C++ 프로그래밍 실행결과 bad_alloc과 같이 프로그래머가 정의하지 않아도 발생하는 예외도 있다. 그리고 Chapter 16에서는 이러한 유형의 예외 중 하나로, 형 변환 시 발생하는 bad_cast 예외를 소개한다.
모든 예외를 처리하는 catch 블록 윤성우의 열혈 C++ 프로그래밍 마지막 catch 블록에 덧붙여지는 경우가 많은데, 대신 catch의 매개변수 선언에서 보이듯이, 발생한 예외와 관련해서 그 어떠한 정보도 전달받을 수 없으며, 전달된 예외의 종류도 구분이 불가능하다.
예외 던지기 윤성우의 열혈 C++ 프로그래밍 실행결과 catch 블록에 전달된 예외는 다시 던져질 수 있다.
Chapter 15가 끝났습니다. 질문 있으신지요?