14. 예외처리
차례 예외 발생 예외 처리 예외 클래스 사용자 예외 클래스
예외 발생 예외 처리 프로그램 실행에서 예외가 발생한 경우에 대한 처리 과정 예외 처리가 없는 경우 정상적인 프로그램 실행이 안될 수도 있음
number2의 값을 0으로 입력한 경우 프로그램 실행이 정상적으로 되지 않음!!! 소스 14-1 (ch14_01.cpp) #include <iostream> using namespace std; int main() { int number1, number2; int quotient, reminder; cout << "수1 : "; cin >> number1; cout << "수2 : "; cin >> number2; quotient=number1/number2; reminder=number1%number2; cout << "몫 : " << quotient << endl; cout << "나머지 : " << reminder << endl; return 0; } number2의 값을 0으로 입력한 경우 프로그램 실행이 정상적으로 되지 않음!!!
소스 14-2 (ch14_02.cpp) number2의 값이 0일 경우에 대한 처리 코드 포함 #include <iostream> using namespace std; int main() { int number1, number2; int quotient, reminder; cout << "수1 : "; cin >> number1; cout << "수2 : "; cin >> number2; if (number2==0) cout << number1 << "은 0으로 나눌 수 없습니다!!" << endl; return 1; } quotient=number1/number2; reminder=number1%number2; cout << "몫 : " << quotient << endl; cout << "나머지 : " << reminder << endl; return 0;
예외처리 try와 catch 1 C++은 예외처리 블록을 제공 try { 예외 발생 여부를 확인해서 발생할 경우 throw 전달인수; 예외가 발생하지 않은 경우 수행할 내용 } catch (throw에서 전달받은 인수) 예외가 발생했을 때 수행할 내용
예외처리 try와 catch 2 try 블록 catch 정상적인 처리 과정 예외 발생시 throw 명령 실행 catch 블록으로 제어 이동함 catch 예외 처리 과정 throw 명령으로 전달된 매개변수 처리
소스 14-3 (ch14_03.cpp) : try~catch 사용 예 cout << "수1 : "; cin >> number1; cout << "수2 : "; cin >> number2; try { if (number2==0) throw number1; quotient=number1/number2; reminder=number1%number2; cout << "몫 : " << quotient << endl; cout << "나머지 : " << reminder << endl; } catch (int e_num) cout << e_num << "은 0으로 나눌 수 없습니다!!" << endl;
소스 14-4 (ch14_04.cpp) : 함수에서 예외 블록 호출하기 1 #include <iostream> using namespace std; double Average(const int total, const int num) { if (total<0 || num==0) throw num; return total/(double)num; } int Sum(const int score1, const int score2, const int score3) if (score1<0 || score2<0 || score3<0) throw 3; return score1+score2+score3; 두 함수 모두 try 블록에서 호출됨
소스 14-4 (ch14_04.cpp) : 함수에서 예외 블록 호출하기 2 int main() { int kor=-100, eng=99, math=98; int total=0; double aver; try total=Sum(kor, eng, math); cout << "합 : " << total << endl; } catch (int i) cout << "*************************************" << endl; cout << i << "개의 과목점수는 0보다 커야 합니다!!!" << endl; Sum() 함수의 throw에 의해 제어가 첫번째 catch 블록으로 이동될 수 있음
소스 14-4 (ch14_04.cpp) : 함수에서 예외 블록 호출하기 3 try { aver=Average(total, 0); cout << "평균 : " << aver << "**" << aver << endl; } catch(int n) cout << "#####################################" << endl; cout << "과목 수는 " << n << "보다 커야 합니다!!!" << endl; return 0; Average() 함수의 throw에 의해 제어가 두번째 catch 블록으로 이동될 수 있음
예외 처리 정보를 함수 선언에 넣기 함수 선언에서 throw 덧붙이기!! int Total(const int k, const int e, const int m); 함수에 예외처리를 덧붙이면 int Total(const int k, const int e, const int m) throw (char *); 예외처리 정보를 함수 선언에 넣는 것에 대해 Visual C++ 컴파일러에서 정확하게 지원하고 있지 않음 이를 해결하기 위해 #pragma warning (disable : 4290) 을 프로그램 코드에 삽입하기 바람
소스 14-5 (ch14_05.cpp) : 함수 선언에서 예외처리 코드 포함하기 1 #include <iostream> #pragma warning( disable : 4290 ) using namespace std; int Total(const int k, const int e, const int m) throw(char *); double Average(const int s, const int num) throw(char *); int main() { int kor=-100, eng=99, math=98; int total=0; double aver; try total=Total(kor, eng, math); aver=Average(total,0); cout << "합 : " << total << endl; cout << "평균 : " << aver << endl; }
소스 14-5 (ch14_05.cpp) : 함수 선언에서 예외처리 코드 포함하기 2 catch (char *msg) { cout << "*************************************" << endl; cout << msg << endl; } return 0; int Total(const int k, const int e, const int m) throw(char *) if (k<0 || e<0 || m<0) throw "과목 점수는 0보다 커야 합니다"; return k+e+m; double Average(const int s, const int num) throw(char *) if (s<0 || num<=0) throw "잘못된 매개변수입니다."; return s/(double)num;
표준 예외 클래스 exception 클래스, exception 클래스를 상속한 여러 파생 클래스들~ exception.h 자주 발생하는 예외처리를 포함함 bad_alloc – new 연산에 의해 발생한 예외처리 bad_cast – dynamic_cast 연산에 의해 발생한 예외처리 등
소스 14-6 (ch14_06.cpp) #include <iostream> #include <exception> using namespace std; int main() { try for (int i=1; i<=100; i++) new int[70000000]; cout << i << "번째 배열이 생성되었습니다." << endl; } catch (bad_alloc &e) cout << "Exception : " << e.what() << endl; return 0; 실행 결과 1번째 배열이 생성되었습니다. 2번째 배열이 생성되었습니다. 3번째 배열이 생성되었습니다. 4번째 배열이 생성되었습니다. 5번째 배열이 생성되었습니다. 6번째 배열이 생성되었습니다. Exception : bad allocation
예외 클래스 예외 클래스 예외 객체 생성시점 관련 내용 runtime_error 실행 오류, <stdexcept> 파생 클래스 : overflow_error, underflow_error bad_alloc 메모리 할당 오류 new bad_cast 형변환 오류 dynamic_cast bad_type_id typeid에 대한 피 연산자가 널 포인터인 경우 typeid bad_exception 예기치 못한 처리 함수 발생 목록에 있지 않은 예외 bad_logic_error 클래스 논리 오류, <stdexcept> 파생 클래스 : invalid_argument, length_error, out_of_range
사용자 예외 클래스 표준 예외 클래스를 상속 받아 사용자 예외 클래스 정의 업무 처리 클래스 - 멤버 함수 내에서 예외가 발생할 경우 throw로 예외 객체 생성하여 catch 블록으로 제어 이동 업무 처리 예외 클래스 멤버 변수나 멤버 함수를 통해 예외 처리 내용을 포함함
실습 세 과목의 성적 처리 클래스와 성적 처리로 인한 예외 사항을 사용자 예외 클래스로 정의해 보자. class Sung { public: Sung(); Sung(const int kor, const int eng, const int math); int GetTotal(); double GetAver(); private : int kor, eng, math,total; double aver; }; class SungException : public logic_error { public : SungException(const int total, const int num); int GetTotal(); int GetNum(); private : int total, num; };
소스 14-7, 14-8 (ch14_sung.h, ch14_sung.cpp) int Sung::GetTotal() { if (kor<=0 || eng<=0 || math<=0) throw SungException(total, 3); //예외 객체 생성하여 전달 total=kor+eng+math; return total; } double Sung::GetAver() if (total<0) aver=total/(double)3; return aver; SungException::SungException(const int total, const int num) : logic_error("잘못된 인수값") //기반 클래스 생성자 호출 { this->total=total; this->num=num; }
소스 14-9 (ch14_07.cpp) #include "ch14_sung.h" int main() { try Sung p1(10, 30, -10); cout << "총점 : " << p1.GetTotal() << endl; cout << "평균 : " << p1.GetAver() << endl; } catch (SungException &e) cout << e.what() << endl; cout << "전달된 총점 : " << e.GetTotal() << endl; cout << "전달된 과목 수 : " << e.GetNum() << endl; return 0;