30
14. 예외처리

14장 - 15장 예외처리, 템플릿

  • Upload
    -

  • View
    111

  • Download
    3

Embed Size (px)

Citation preview

Page 1: 14장 - 15장 예외처리, 템플릿

14. 예외처리

Page 2: 14장 - 15장 예외처리, 템플릿

차례 예외 발생

예외 처리

예외 클래스

사용자 예외 클래스

2/14

Page 3: 14장 - 15장 예외처리, 템플릿

예외 발생 예외 처리

–프로그램 실행에서 예외가 발생한 경우에 대한 처리 과정

–예외 처리가 없는 경우 정상적인 프로그램 실행이 안될 수도 있음

3/14

Page 4: 14장 - 15장 예외처리, 템플릿

4/14

소스 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으로 입력한 경우 프로그램 실행이 정상적으로 되지 않음!!!

Page 5: 14장 - 15장 예외처리, 템플릿

5/14

소스 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; }

Page 6: 14장 - 15장 예외처리, 템플릿

예외처리 try와 catch 1 C++은 예외처리 블록을 제공

6/14

try { 예외 발생 여부를 확인해서 발생할 경우 throw 전달인수; 예외가 발생하지 않은 경우 수행할 내용 } catch (throw에서 전달받은 인수) { 예외가 발생했을 때 수행할 내용 }

Page 7: 14장 - 15장 예외처리, 템플릿

예외처리 try와 catch 2 try 블록

–정상적인 처리 과정

–예외 발생시 throw 명령 실행 catch 블록으로 제어 이동함

catch

–예외 처리 과정

– throw 명령으로 전달된 매개변수 처리

7/14

Page 8: 14장 - 15장 예외처리, 템플릿

8/14

소스 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; }

Page 9: 14장 - 15장 예외처리, 템플릿

9/14

소스 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 블록에서 호출됨

Page 10: 14장 - 15장 예외처리, 템플릿

10/14

소스 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 블록으로 이동될 수 있음

Page 11: 14장 - 15장 예외처리, 템플릿

11/14

소스 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 블록으로 이동될 수 있음

Page 12: 14장 - 15장 예외처리, 템플릿

예외 처리 정보를 함수 선언에 넣기 함수 선언에서 throw 덧붙이기!!

12/14

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) 을 프로그램 코드에 삽입하기 바람

Page 13: 14장 - 15장 예외처리, 템플릿

13/14

소스 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; }

Page 14: 14장 - 15장 예외처리, 템플릿

14/14

소스 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; }

Page 15: 14장 - 15장 예외처리, 템플릿

표준 예외 클래스 exception 클래스, exception 클래스를 상속한 여러 파생 클래스들~

– exception.h

–자주 발생하는 예외처리를 포함함

• bad_alloc – new 연산에 의해 발생한 예외처리

• bad_cast – dynamic_cast 연산에 의해 발생한 예외처리 등

15/14

Page 16: 14장 - 15장 예외처리, 템플릿

16/14

소스 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

Page 17: 14장 - 15장 예외처리, 템플릿

예외 클래스

17/14

예외 클래스 예외 객체 생성시점 관련 내용

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

Page 18: 14장 - 15장 예외처리, 템플릿

사용자 예외 클래스 표준 예외 클래스를 상속 받아 사용자 예외 클래스 정의

18/14

업무 처리 클래스 - 멤버 함수 내에서 예외가 발생할 경우 throw로 예외 객체 생성하여 catch 블록으로 제어 이동

업무 처리 예외 클래스 -멤버 변수나 멤버 함수를 통해 예외 처리 내용을 포함함

Page 19: 14장 - 15장 예외처리, 템플릿

실습

19/14

세 과목의 성적 처리 클래스와 성적 처리로 인한 예외 사항을 사용자 예외 클래스로 정의해 보자.

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; };

Page 20: 14장 - 15장 예외처리, 템플릿

20/14

소스 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) throw SungException(total, 3); //예외 객체 생성하여 전달 aver=total/(double)3; return aver; }

SungException::SungException(const int total, const int num) : logic_error("잘못된 인수값") //기반 클래스 생성자 호출 { this->total=total; this->num=num; }

Page 21: 14장 - 15장 예외처리, 템플릿

21/14

소스 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; }

Page 22: 14장 - 15장 예외처리, 템플릿

15. 템플릿

Page 23: 14장 - 15장 예외처리, 템플릿

차례 함수 템플릿

클래스 템플릿

23/9

Page 24: 14장 - 15장 예외처리, 템플릿

함수 템플릿 함수 템플릿

–함수의 처리 절차는 동일하나 처리 대상이 상황에 따라 여러 자료형일 경우 함수 오버로딩으로 정의할 경우 대상 자료형 개수 만큼의 함수 정의가 있어야 함

–함수 템플릿은 함수 내에서 사용하는 자료형을 일반화된 유형으로 정의하여 하나의 함수를 정의하고 함수 호출에서 적절한 자료형을 대입해서 사용

24/9

Page 25: 14장 - 15장 예외처리, 템플릿

함수 템플릿 구현 함수의 헤더(함수 선언과 함수 정의)에 일반화된 자료형 명시

두 개의 수 중에서 큰 값을 리턴하는 함수

template<typename 일반화유형이름>

함수 선언 : template<typename T> T MaxValue(const T num1, const T num2);

함수 정의 : template<typename T> T MaxValue(const T num1, const T num2) { if (num1>num2) return num1; else return num2; }

25/9

Page 26: 14장 - 15장 예외처리, 템플릿

소스 15-1 (ch15_01.cpp)

#include <iostream> using namespace std; template<typename T> T MaxValue(const T num1, const T num2) { if (num1>num2) return num1; else return num2; } int main() { cout << "정수 비교 결과 : " << MaxValue(3, 5) << endl; cout << "배정도 비교 결과 : " << MaxValue(9.1, 3.6) << endl; return 0; } 26/9

Page 27: 14장 - 15장 예외처리, 템플릿

클래스 템플릿 1 클래스 내에 사용되는 자료형을 일반화 유형으로 표기

클래스의 멤버 변수나 멤버 변수의 반환 자료형 등을 일반화 유형으로 사용할 수 있음

클래스 선언 클래스 멤버 함수 정의

template<typename 일반화유형이름> class 클래스이름 { ….. };

template<typename 일반화유형이름> 리턴형 클래스이름<일반화유형이름>::멤버함수(매개변수) { ….. }

27/9

Page 28: 14장 - 15장 예외처리, 템플릿

클래스 템플릿 2 클래스 멤버 함수 정의에서 생성자를 포함해서 매번 일반화 유형을 함수 머리 부분 위에 명시해야 함

객체 생성시 일반화 유형 명시 해야 함

클래스 템플릿은 클래스 템플릿 자체가 선언의 의미가 있어 클래스 선언과 정의가 하나의 파일에 있어야 함!!!

클래스이름 <일반화유형에 대치될 자료형> 객체이름;

28/9

Page 29: 14장 - 15장 예외처리, 템플릿

소스 15-2 (ch15_sung.h)

#ifndef _SUNG_H_ #define _SUNG_H_ #include <iostream> using namespace std; template<typename T> class SUNG { public : SUNG(const T k, const T e, const T m); T GetSum(); double GetAver(); private : T k,e,m,sum; double aver; };

template<typename T> SUNG<T>::SUNG(const T k, const T e, const T m) { this->k=k; this->e=e; this->m=m; } template<typename T> T SUNG<T>::GetSum() { sum=k+e+m; return sum; } template<typename T> double SUNG<T>::GetAver() { aver=sum/(double)3; return aver; } #else #endif 29/9

Page 30: 14장 - 15장 예외처리, 템플릿

소스 15-3 (ch15_02.cpp)

#include "ch15_sung.h" int main() { SUNG<int> intSung(90, 87, 65); cout << "총점 : " << intSung.GetSum() << endl; cout << "평균 : " << intSung.GetAver() << endl; SUNG<double> dSung(34.6, 98.6, 88.9); cout << "총점 : " << dSung.GetSum() << endl; cout << "평균 : " << dSung.GetAver() << endl; return 0; }

30/9