본 단계에서는 다음ㅇ의 예외상황에 대한 처리를 C++의 예외처리 기반으로 작용하고자 한다.
이 두 가지 예외상황의 처리를 위해서 예외상황 별로 각각 예외 클래스를 정의하기로 하고, 프로그램 사용자에게는 잘못된 입력이 이뤄졌음을 알리고 재 입력을 요구하는 방식으로 예외상황이 처리되도록 하자.
예외의 발생 및 처리의 위치를 여러분께 먼저 알려드리게 되면, 그만큼 이번 단계의 프로젝트를 무의미하게 만드는 셈이 된다.
따라서 이 모든 것을 여러분이 직접 결정하는 기회로 삼기 바란다.
참고로, 필자가 이후에 제시하는 답안과 차이가 있다고 해서 잘못된 것은 아니다.
예외의 처리는 다양한 방법으로 진행이 될 수 있기 때문에, 일단은 결과를 가지고 판단해야 한다.
따라서 위에서 말한 다음의 요구사항을 모두 충족시킨다면,
"예외상황의 처리를 위해서 예외상황 별로 각각 예외 클래스를 정의한다."
"예외상황 발생시 재 입력을 요구하는 방식으로 예외상황을 처리하자."
일단 모범답안으로 인정할 수 있다. 물론 다양한 가능성을 놓고, 보다 나은 것은 무엇인지 고민하는 시간을 가질 필요는 있다.
Account.cpp
#include "BankingCommonDecl.h"
#include "Account.h"
#include "AccountException.h"
Account::Account(int id, int money, String name) // -------- 변경
:accID(id), balance(money), cusName(name) {}
//------ 복사, 대입, 소멸자 삭제
int Account::GetAccID() const { return accID; }
void Account::Deposit(int money) {
if (money < 0)
throw DepositException(money);
balance += money;
}
int Account::Withdraw(int money) {
if (balance < money)
throw WithdrawException(money);
balance -= money;
return money;
}
void Account::ShowAccInfo() const {
cout << "계좌ID: " << accID << endl;
cout << "이 름: " << cusName << endl;
cout << "잔 액: " << balance << endl;
}
Normal.cpp
#ifndef __NORMAL_ACCOUNT_H__
#define __NORMAL_ACCOUNT_H__
#include "Account.h"
#include "String.h"
#include "AccountException.h"
class NormalAccount : public Account {
int interRate;
public:
NormalAccount(int id, int money, String name, int rate)
:Account(id, money, name), interRate(rate)
{}
virtual void Deposit(int money) {
if (money < 0)
throw DepositException(money);
Account::Deposit(money);
Account::Deposit(money * (interRate / 100.0));
}
};
#endif
HighCreditAccount.h
#ifndef __HIGHCREDIT_ACCOUNT_H__
#define __HIGHCREDIT_ACCOUNT_H__
#include "NormalAccount.h"
#include "String.h"
class HighCreditAccount : public NormalAccount {
int specialRate;
public:
HighCreditAccount(int id, int money, String name, int rate, int special)
:NormalAccount(id, money, name, rate), specialRate(special)
{}
virtual void Deposit(int money) {
if (money < 0)
throw DepositException(money);
NormalAccount::Deposit(money);
Account::Deposit(money * (specialRate / 100.0));
}
};
#endif
AccountHandler.cpp
#include "BankingCommonDecl.h"
#include "AccountHandler.h"
#include "Account.h"
#include "NormalAccount.h"
#include "HighCreditAccount.h"
#include "AccountException.h"
AccountHandler::AccountHandler() : accNum(0) {}
void AccountHandler::ShowMenu() const {
cout << "-----Menu-----" << endl;
cout << "1. 계좌개설" << endl;
cout << "2. 입 금" << endl;
cout << "3. 출 금" << endl;
cout << "4. 계좌정보 전체 출력" << endl;
cout << "5. 프로그램 종료" << endl;
}
void AccountHandler::MakeAccount() {
int input;
cout << "[계좌종류선택]" << endl;
cout << "1. 보통예금계좌 2. 신용신뢰계좌 " << endl;
cout << "선택: ";
cin >> input;
if (input == NORMAL)
MakeNormalAccount();
else
MakeCreditAccount();
}
void AccountHandler::MakeNormalAccount() {
int id;
String name; //-------- 변경
int balance;
int interRate;
cout << "[보통예금계좌 개설]" << endl;
cout << "계좌ID: "; cin >> id;
cout << "이 름: "; cin >> name;
cout << "입금액: "; cin >> balance;
cout << "이자율: "; cin >> interRate;
cout << endl;
accArr[accNum++] = new NormalAccount(id, balance, name, interRate);
}
void AccountHandler::MakeCreditAccount() {
int id;
String name; // -------- 변경
int balance;
int interRate;
int creditLevel;
cout << "[신용신뢰계좌 개설]" << endl;
cout << "계좌ID: "; cin >> id;
cout << "이 름: "; cin >> name;
cout << "입금액: "; cin >> balance;
cout << "이자율: "; cin >> interRate;
cout << "신용등급(1toA, 2toB, 3toC): "; cin >> creditLevel;
cout << endl;
switch (creditLevel) {
case 1:
accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, LEVEL_A);
break;
case 2:
accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, LEVEL_B);
break;
case 3:
accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, LEVEL_C);
break;
}
}
void AccountHandler::DepositMoney() {
int money;
int id;
cout << "[입 금]" << endl;
cout << "계좌ID: "; cin >> id;
while (true) {
cout << "입금액: "; cin >> money;
try {
for (int i = 0; i < accNum; i++) {
if (accArr[i]->GetAccID() == id) {
accArr[i]->Deposit(money);
cout << "입금완료" << endl << endl;
return;
}
}
cout << "유효하지 않은 ID 입니다." << endl << endl;
return;
}
catch (AccountException& expt) {
expt.ShowExceptionReason();
cout << "입금액만 재입력하세요." << endl;
}
}
}
void AccountHandler::WithdrawMoney() {
int money;
int id;
cout << "[출 금]" << endl;
cout << "계좌ID: "; cin >> id;
while (true) {
cout << "출금액: "; cin >> money;
try {
for (int i = 0; i < accNum; i++) {
if (accArr[i]->GetAccID() == id) {
accArr[i]->Withdraw(money);
cout << "출금완료" << endl << endl;
return;
}
}
cout << "유효하지 않은 ID 입니다." << endl << endl;
return;
}
catch(AccountException& expt) {
expt.ShowExceptionReason();
cout << "출금액만 재입력하세요." << endl;
}
}
}
void AccountHandler::ShowAllAccInfo() const {
for (int i = 0; i < accNum; i++) {
accArr[i]->ShowAccInfo();
cout << endl;
}
}
AccountHandler::~AccountHandler() {
for (int i = 0; i < accNum; i++)
delete accArr[i];
}
AccountException.h
#ifndef __ACCOUNT_EXCEPTION_H__
#define __ACCOUNT_EXCEPTION_H__
#include "BankingCommonDecl.h"
class AccountException {
public:
virtual void ShowExceptionReason() const = 0;
};
class DepositException : public AccountException {
int reqDep; // 요청 입금액
public:
DepositException(int money) : reqDep(money) {}
void ShowExceptionReason()const {
cout << "[예외 메시지: " << reqDep << "는 입금 불가]" << endl;
}
};
class WithdrawException : public AccountException {
int balance;
public:
WithdrawException(int money) : balance(money) {}
void ShowExceptionReason() const {
cout << "[예외 메시지: 잔액" << balance << ", 잔액부족]" << endl;
}
};
#endif