728x90
728x90

상속의 목적은 명확해야 하고 그렇지 않다면 안하는 편이 좋다.
상속이 필요한 대표적이며 중요한 이유, 이점을 정리해본다.

공통적인 기능을 묶어 추가 삭제 등 변경사항이 생겨도 자식 클래스에 일일히 적용하지 않아도 된다 -> 확장성이 좋다
다른 곳에도 구현해 둔 클래스를 붙였다 뗐다 할 수 있다 -> 재사용이 가능

● 장점 : 유지보수가 쉬워지고, 확장성이 좋아지며, 모듈화를 통해 재사용이 가능하며, 코드가 간결해져 개발시간을 단축시킬 수 있다.

 

 

과거 진행한 OOP 단계별 프로젝트

[윤성우 열혈 c++] OOP 단계별 프로젝트 01단계

[윤성우 열혈 c++] OOP 단계별 프로젝트 02단계

[윤성우 열혈 c++] OOP 단계별 프로젝트 03단계

[윤성우 열혈 c++] OOP 단계별 프로젝트 04단계

[윤성우 열혈 c++] OOP 단계별 프로젝트 05단계

 

 

프로그램 설명

기존 Account 클래스에는 이자와 관련한 부분이 없으니 6단계에서는 Account 클래스를 상속하는 2개의 클래스를 추가 정의한다.

1) NormalAccount  :  보통예금계좌 (최소한의 이자를 지급하는 자유입출금계좌)
2) HighCreditAccount  :  신용신뢰계좌 (신용도가 높은 일부 고객만 개설되는 높은 이율 계좌)

NormalAccount  클래스는 객체의 생성 과정에서(생성자를 통해) 이율정보를 등록할 수 있게 정의한다.
HighCreditAccount 클래스에는 다음 특성을 부여해 정의하자.

1) NormalAccount 클래스처럼 객체 생성과정에서 기본이율을 등록할 수 있다
2) 고객의 신용등급을 A, B, C로 나누고 계좌개설 시 신용등급 정보를 등록한다.
3) A, B, C 등급별로 각각 기본이율에 7%, 4%, 2%의 이율을 추가 제공한다.

편의상 이자는 입금 시 이자가 원금에 더해지는 것으로 계산한다.
모든 계좌에는 다음 조건을 적용한다.

1) 계좌개설 과정에서 초기 입금되는 금액에 대해서는 이자를 계산하지 않는다.
2) 계좌개설 후 별도의 입금과정을 거칠 때에만 이자가 발생하는 것으로 간주한다.
3) 이자의 계산과정에서 발생하는 소수점 이하의 금액은 무시한다.

컨트롤 클래스인 AccountHandler 클래스에는 큰 변화가 없어야 한다.
(계좌의 종류가 늘어난 만큼 메뉴의 선택과 데이터의 입력과정에서의 불가피한 변경은 허용)

 

 

실행의 예

계좌의 개설과정 1

-----Menu-----
1. 계좌개설
2. 입금
3. 출금
4. 계좌번호 전체 출력
5. 프로그램 종료
선택: 1


[계좌종류선택]
1. 보통예금계좌 2. 신용신뢰계좌
선택 : 1

[보통예금계좌 개설]
계좌ID: 123
이름: 이종석
입금액: 0
이자율: 3

 

 

계좌의 개설과정 2

-----Menu-----
1. 계좌개설
2. 입금
3. 출금
4. 계좌번호 전체 출력
5. 프로그램 종료
선택: 1


[계좌종류선택]
1. 보통예금계좌 2. 신용신뢰계좌
선택 : 2

[신용신뢰계좌 개설]
계좌ID: 7272
이름: 이수혁
입금액: 10000
이자율: 9
신용등급(1toA, 2toB, 3toC): 2

 

 

 

 

 

 

구현코드는 나름대로 나눠서 정리해 봤다.

 

BankingSystemMain.cpp
// BankingSystemVer06.cpp - 은행 계좌 관리 프로그램 6
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstring> 

#include "Account.h"
#include "AccountHandler.h"
#include "NormalAccount.h"
#include "HighCreditAccount.h"

using namespace std;

//1. 계좌개설
//2. 입금
//3. 출금
//4. 계좌번호 전체 출력
//5. 프로그램 종료
enum { MAKE = 1, DEPOSIT, WITHDRAW, INQUIRE, EXIT };

/********** 메인 클래스 AccountHandler **********/
int main()
{
    AccountHandler hdr;
    int choice;

    while (1)
    {
        hdr.ShowMenu(); //메뉴선택모드

        cout << "선택(1~5까지의 숫자만 입력) : ";
        cin >> choice;
        cout << endl;

        switch (choice)
        {
        case MAKE:
            hdr.MakeAccount();
            break;
        case DEPOSIT:
            hdr.DepositMoney();
            break;
        case WITHDRAW:
            hdr.WithdrawMoney();
            break;
        case INQUIRE:
            hdr.ShowAllAccInfo();
            break;
        case EXIT:
            return 0;
        default:
            cout << "잘못된 선택" << endl;
        }
    }
    return 0;
}

 

 

 

Account.h, Account.cpp
#pragma once
class Account {
private:
    int accID; //계좌 ID
    int balance; // 잔액
    char* cusName; //고객이름 
public:
    Account(int _accID, int _balance, char* _name); //생성자
    Account(const Account& ref); //복사생성자

    int GetAccID() const;    // 계좌 ID 반환 
    virtual void Deposit(int money); // 입금     //virtual 추가
    int WithDraw(int money);  // 출금
    void ShowAccInfo() const;  // 개인계좌조회   

    ~Account(); // 소멸자
};
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Account.h"
using namespace std;

// Account 생성자 
Account::Account(int _accID, int _balance, char* _name)  // 계좌개설 - ID, 고객이름, 돈
    : accID(_accID), balance(_balance)
{
    cusName = new char[strlen(_name) + 1]; //고객이름 객체 포인터로 동적할당
    strcpy(cusName, _name);
}

// 실제 호출되지는 않는 Account복사생성자
// 깊은 복사를 원칙으로 정의
Account::Account(const Account& ref)
    : accID(ref.accID), balance(ref.balance)
{
    cusName = new char[strlen(ref.cusName) + 1]; //고객이름 객체 포인터로 동적할당
    strcpy(cusName, ref.cusName);
}

// Account 소멸자
Account::~Account() // 소멸자
{
    delete[] cusName;
}

// 계좌 ID 반환
int Account::GetAccID() const  // 내부 출력문이나 값의 변동이 없는 경우 const
{
    return accID;
}

// 개인 계좌조회
void Account::ShowAccInfo() const
{
    // 내부 출력문이나 값의 변동이 없는 경우 const
    cout << "계좌ID: " << accID << endl;
    cout << "이름: " << cusName << endl;
    cout << "잔액: " << balance << endl << endl;
}

// 입출금
void Account::Deposit(int money)
{
    balance += money;
}
int Account::WithDraw(int money)
{
    if (balance < money) //잔액<출금액 
    {
        return 0;
    }
    balance -= money;
    return money;
}

 

 

 

AccountHandler.h, AccountHandler.cpp
#pragma once
/********** 컨트롤 클래스 AccountHandler **********/
class AccountHandler {
private:
    // 전역 변수였던 것들
    Account* accArr[100]; //Account 저장을 위한 배열
    int accNum; //저장된 Account 수    
public:
    AccountHandler();  //생성자

    // 전역함수였던 것들
    void ShowMenu(void) const; //메뉴출력
    void MakeAccount(void); //계좌개설
    void DepositMoney(void); //입금
    void WithdrawMoney(void); //출금
    void ShowAllAccInfo(void) const; //잔액조회

    void MakeNormalAccount(); // 보통예금계좌 개설
    void MakeHighCreditAccount(); // 신용신뢰계좌 개설

    ~AccountHandler(); //소멸자
};
#include <iostream>
#include "Account.h"
#include "AccountHandler.h"
#include "NormalAccount.h"
#include "HighCreditAccount.h"

using namespace std;

const int NAME_LEN = 20; //이름의길이

//메뉴출력
void AccountHandler::ShowMenu(void) const {
    cout << "-----Menu-----" << endl;
    cout << "1. 계좌개설" << endl;
    cout << "2. 입금" << endl;
    cout << "3. 출금" << endl;
    cout << "4. 계좌번호 전체 출력" << endl;
    cout << "5. 프로그램 종료" << endl;
}

// AccountHandler 생성자
AccountHandler::AccountHandler()
    : accNum(0)
{}

// AccountHandler 소멸자
AccountHandler::~AccountHandler()
{
    for (int i = 0; i < accNum; i++)
    {
        delete accArr[i];
    }
}

// 계좌종류
enum AccountType { NORMAL = 1, HIGHCREDIT };

// 신용등급
enum CreditRating { A = 7, B = 4, C = 2 };


//계좌개설
void AccountHandler::MakeAccount(void)
{
   /* int id;
    char name[NAME_LEN];
    int balance;*/
    int accountType; 

   /* cout << "[계좌개설]" << endl;
    cout << "계좌ID:(숫자로 입력) "; cin >> id;
    cout << "이름: "; cin >> name;
    cout << "입금액: "; cin >> balance;
    cout << endl;
    accArr[accNum++] = new Account(id, balance, name);*/

    cout << "[계좌종류선택]" << endl;
    cout << "1. 보통예금계좌 2. 신용신뢰계좌" << endl;
    cout << "선택(숫자입력) : "; cin >> accountType;

    if (accountType == NORMAL) //보통예금계좌
    {      
        MakeNormalAccount();
    }
    else // 신용신뢰계좌
    {
        MakeHighCreditAccount();
    }       
}


// 보통예금계좌 개설
void AccountHandler::MakeNormalAccount()
{
    int id;
    char name[NAME_LEN];
    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::MakeHighCreditAccount()
{
    int id;
    char name[NAME_LEN];
    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이며 1, 2, 3 중 입력): "; cin >> creditLevel;
    cout << endl;    
    
    // 신용등급 처리   
    switch (creditLevel)
    {
    case 1: 
        // 1을 입력했을 때
        accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, A); //7%
        break;
    case 2:
        accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, B); //4%
        break;
    case 3:
        accArr[accNum++] = new HighCreditAccount(id, balance, name, interRate, C); //2%
        break;
    }    
}




//입금
void AccountHandler::DepositMoney(void) {
    int money;
    int id;
    cout << "[입  금]" << endl;
    cout << "계좌ID: "; cin >> id;
    cout << "입금액: "; cin >> money;


    for (int i = 0; i < accNum; i++)
    {
        if (accArr[i]->GetAccID() == id)
        {
            accArr[i]->Deposit(money);
            cout << "입금완료" << endl << endl;
            return;
        }
    }
    cout << "유효하지 않은 ID 입니다." << endl << endl;
}

//출금
void AccountHandler::WithdrawMoney(void) {
    int money;
    int id;
    cout << "[출  금]" << endl;
    cout << "계좌ID: "; cin >> id;
    cout << "출금액: "; cin >> money;

    for (int i = 0; i < accNum; i++)
    {
        if (accArr[i]->GetAccID() == id)
        {
            if (accArr[i]->WithDraw(money) == 0) //잔액보다 출금액이 크면
            {
                cout << "잔액부족" << endl << endl;
                return;
            }
            cout << "출금완료" << endl << endl;
            return;
        }
    }
    cout << "유효하지 않은 ID 입니다" << endl << endl;
}

// 전체고객 잔액조회
void AccountHandler::ShowAllAccInfo(void) const
{
    for (int i = 0; i < accNum; i++)
    {
        accArr[i]->ShowAccInfo();
    }
}

 

 

 

NormalAccount.h, NormalAccount.cpp
#pragma once
/**
*	객체를 생성할 때 계좌 기본이율을 등록할 수 있다
*	계좌개설 과정 초기 입금액은 이자가 붙지 않는다.
*	이자계산액의 소수점 이하 금액은 무시한다. (버림)
*/
class NormalAccount: public Account //Account 상속
{
public:
	NormalAccount(int _accID, int _balance, char* _name, int _basicInterestRate);
	~NormalAccount();
private:
	int basicInterestRate; // 기본이율 (%단위)

public:
	//추가된 입금 + 이자율 계산식......뒤집어쓰니까 virtual
	virtual void Deposit(int money);
};
#include <iostream>
#include "Account.h"
#include "NormalAccount.h"

NormalAccount::NormalAccount(int _accID, int _balance, char* _name, int _basicInterestRate)
	: Account(_accID, _balance, _name), basicInterestRate(_basicInterestRate)
{ }

NormalAccount::~NormalAccount()	
{ }

void NormalAccount::Deposit(int money)
{
	Account::Deposit(money); //원금추가
	Account::Deposit(money*(basicInterestRate/100.0)); //이자추가
}

 

 

 

HighCreditAccounth, HighCreditAccount.cpp
#pragma once
/**
*	객체를 생성할 때 계좌 기본이율을 등록할 수 있다
*	계좌개설 과정 초기 입금액은 이자가 붙지 않는다.
*	이자계산액의 소수점 이하 금액은 무시한다. (버림)
*	신용등급 정보 A(7%), B(4%), C(2%) 셋 중 하나를 계좌개설 시 등록한다.
*	등급별 기본이율에 각각의 이율을 추가 제공한다.
*/
class HighCreditAccount : public NormalAccount
{
public:
	HighCreditAccount(int _id, int _balance, char* _name, int _interRate, int _creditLevel);
	~HighCreditAccount();
private: 
	int creditLevel; //신용등급
public:
	virtual void Deposit(int money);
};
#include <iostream>
#include "Account.h"
#include "NormalAccount.h"
#include "HighCreditAccount.h"

HighCreditAccount::HighCreditAccount(int _id, int _balance, char* _name, int _interRate, int _creditLevel)
	: NormalAccount(_id, _balance, _name, _interRate), creditLevel(_creditLevel)
{	}

HighCreditAccount::~HighCreditAccount()
{	}

void HighCreditAccount::Deposit(int money)
{
	NormalAccount::Deposit(money); //원금과 이자추가 
	Account::Deposit(money*(creditLevel/100.0)); // 특별이자 추가
}

 

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,

v