일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- LG
- 분류
- Classification
- 해커톤
- Machine Learning
- LG Aimers 4th
- LG Aimers
- 회귀
- 머신러닝
- LLM
- 오블완
- supervised learning
- OpenAI
- AI
- 딥러닝
- deep learning
- 티스토리챌린지
- PCA
- 지도학습
- gpt
- ChatGPT
- GPT-4
- regression
Archives
- Today
- Total
SYDev
C++ Chapter 15-4 : 예외상황을 표현하는 예외 클래스의 설계 본문
예외 클래스와 예외 객체
- 예외 객체: 예외 발생을 알리는데 사용되는 객체
- 예외 클래스: 예외객체의 생성을 위해 정의된 클래스
이와 관련된 예제를 살펴보자.
#include <iostream>
#include <cstring>
using namespace std;
class DepositException
{
private:
int reqDep; //요청 입금액
public:
DepositException(int money) : reqDep(money)
{ }
void ShowExceptionReason()
{
cout<<"[예외 메시지: "<<reqDep<<"는 입금불가]"<<endl;
}
};
class WithdrawException
{
private:
int balance; //잔고
public:
WithdrawException(int money) : balance(money)
{ }
void ShowExceptionReason()
{
cout<<"[예외 메시지: 잔액 "<<balance<<", 잔액부족]"<<endl;
}
};
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();
try
{
myAcc.Withdraw(3500);
myAcc.Withdraw(4500);
}
catch(WithdrawException &expn) //굳이 예외객체를 복사할 필요가 없기 때문에 참조자 선언
{
expn.ShowExceptionReason();
}
myAcc.ShowMyMoney();
return 0;
}
[예외 메시지: -300는 입금불가]
잔고: 7000
[예외 메시지: 잔액 3500, 잔액부족]
잔고: 3500
상속관계에 있는 예외 클래스
예외 클래스도 상속의 관계를 구성할 수 있다.
이를 바탕으로 예제를 확장해보자.
#include <iostream>
#include <cstring>
using namespace std;
class AccountException
{
public:
virtual void ShowExceptionReason()=0; //순수 가상함수
};
class DepositException : public AccountException
{
private:
int reqDep;
public:
DepositException(int money) : reqDep(money)
{ }
void ShowExceptionReason()
{
cout<<"[예외 메시지: "<<reqDep<<"는 입금불가]"<<endl;
}
};
class WithdrawException : public AccountException
{
private:
int balance;
public:
WithdrawException(int money) : balance(money)
{ }
void ShowExceptionReason()
{
cout<<"[예외 메시지: 잔액 "<<balance<<", 잔액부족]"<<endl;
}
};
class Account
{
private:
char accNum[50];
int balance;
public:
Account(char * acc, int money) : balance(money)
{
strcpy(accNum, acc);
}
void Deposit(int money) throw (AccountException) //상속에 의해 DepositionException 객체도 AccountException 객체로 간주
{
if(money<0)
{
DepositException expn(money);
throw expn;
}
balance+=money;
}
void Withdraw(int money) throw (AccountException) //상속에 의해 WithdrawException 객체도 AccountException 객체로 간주
{
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(AccountException &expn)
{
expn.ShowExceptionReason();
}
myAcc.ShowMyMoney();
try
{
myAcc.Withdraw(3500);
myAcc.Withdraw(4500);
}
catch(AccountException &expn)
{
expn.ShowExceptionReason();
}
myAcc.ShowMyMoney();
return 0;
}
[예외 메시지: -300는 입금불가]
잔고: 7000
[예외 메시지: 잔액 3500, 잔액부족]
잔고: 3500
예제와 같이 예외 클래스를 묶으면, 예외의 처리를 단순화할 수 있다.
예외의 전달방식에 따른 주의사항
try 블록에 이어서 등장하는 catch 블록이 둘 이상인 경우, 위에서 아래로 catch 블록을 찾아서 내려간다. 그렇기 때문에 다음 구조는 적절하지 않다.
#include <iostream>
using namespace std;
class AAA
{
public:
void ShowYou() { cout<<"AAA exception!"<<endl; }
};
class BBB : public AAA
{
public:
void ShowYou() { cout<<"BBB exception!"<<endl; }
};
class CCC : public BBB
{
public:
void ShowYou() { cout<<"CCC exception!"<<endl; }
};
void ExceptionGenerator(int expn)
{
if(expn==1)
throw AAA();
else if(expn==2)
throw BBB();
else
throw CCC();
}
int main(void)
{
try
{
ExceptionGenerator(3);
ExceptionGenerator(2);
ExceptionGenerator(1);
}
catch(AAA& expn)
{
cout<<"catch(AAA& expn)"<<endl;
expn.ShowYou();
}
catch(BBB& expn)
{
cout<<"catch(BBB& expn)"<<endl;
expn.ShowYou();
}
catch(CCC& expn)
{
cout<<"catch(CCC& expn)"<<endl;
expn.ShowYou();
}
return 0;
}
catch(AAA& expn)
AAA exception!
위의 경우 클래스 BBB와 CCC가 클래스 AAA를 상속하기 때문에 해당 클래스의 객체들이 모두 AAA의 객체로 취급되어, AAA의 객체를 매개변수로 받는 catch 블록에서 걸러지게 된다. BBB 예외객체는 BBB 객체를 매개변수로 받는 catch 블록에서 처리가 되고, CCC도 그렇게 처리하고 싶다면 다음과 같이 구조를 바꿔야 한다.
catch(CCC& expn)
{
cout<<"catch(CCC& expn)"<<endl;
expn.ShowYou();
}
catch(BBB& expn)
{
cout<<"catch(BBB& expn)"<<endl;
expn.ShowYou();
}
catch(AAA& expn)
{
cout<<"catch(AAA& expn)"<<endl;
expn.ShowYou();
}
참고자료
- 윤성우, <윤성우의 열혈 C++ 프로그래밍>, 오렌지미디어, 2010.05.12
'Programming Lang > C++' 카테고리의 다른 글
C++ Chapter 16-1 : C++에서의 형 변환 연산 (0) | 2023.08.01 |
---|---|
C++ Chapter 15-5 : 예외처리와 관련된 또 다른 특성들 (0) | 2023.08.01 |
C++ Chapter 15-3 : Stack Unwinding(스택 풀기) (0) | 2023.08.01 |
C++ Chapter 15-2 : C++의 예외처리 메커니즘 (0) | 2023.08.01 |
C++ Chapter 15-1 : 예외상황과 예외처리의 이해 (0) | 2023.08.01 |