[C++] 윤성우 열혈 - OOP 단계별 프로젝트 04단계 (friend, static, const)

Kim Dongil·2022년 12월 9일
0

C++

목록 보기
8/23

버전 0.3 에서 만들었던 은행계좌 관리 프로그램을 버전 0.4 로 업그레이드 시켜보자.
선언이 가능한 모든 멤버함수를 const 로 선언하자.

#include <iostream>
#include <cstring>

using namespace std;
const int NAME_LEN = 20;

void ShowMenu(void);       // 메뉴출력
void MakeAccount(void);    // 계좌개설을 위한 함수
void DepositMoney(void);       // 입    금
void WithdrawMoney(void);      // 출    금
void ShowAllAccInfo(void);     // 잔액조회

enum { MAKE = 1, DEPOSIT, WITHDRAW, INQUIRE, EXIT };

class Account {
	int accID;      // 계좌번호
	int balance;    // 잔    액
	char* cusName;   // 고객이름

public:
	Account(int ID, int money, char* name)
		: accID(ID), balance(money) {
		cusName = new char[strlen(name) + 1];
		strcpy(cusName, name);
	}
	Account(const Account& copy) : accID(copy.accID), balance(copy.balance) {
		cusName = new char[strlen(copy.cusName) + 1];
		strcpy(cusName, copy.cusName);
	}

	int GetAccID() const { return accID; }

	void Deposit(const int money) {
		balance += money;
	}

	int Withdraw(const int money) {   // 출금액 반환, 부족 시 0
		if (balance < money)
			return 0;

		balance -= money;
		return money;
	}

	void ShowAccInfo() const {
		cout << "계좌ID: " << accID << endl;
		cout << "이  름: " << cusName << endl;
		cout << "잔  액: " << balance << endl;
	}

	~Account() {
		delete[]cusName;
	}
};

Account* accArr[100];   // Account 저장을 위한 배열
int accNum = 0;        // 저장된 Account 수

int main(void) {
	int choice;

	while (1) {
		ShowMenu();
		cout << "선택: ";
		cin >> choice;
		cout << endl;

		switch (choice) {
		case MAKE:
			MakeAccount();
			break;
		case DEPOSIT:
			DepositMoney();
			break;
		case WITHDRAW:
			WithdrawMoney();
			break;
		case INQUIRE:
			ShowAllAccInfo();
			break;
		case EXIT:
			cout << "프로그램을 종료합니다." << endl;
			return 0;
		default:
			cout << "잘못된 입력입니다. 다시 입력해 주세요" << endl;
		}
	}

	for (int i = 0; i < accNum; i++)
		delete accArr[i];
	return 0;
}

void ShowMenu(void) {
	cout << "-----Menu------" << endl;
	cout << "1. 계좌개설" << endl;
	cout << "2. 입    금" << endl;
	cout << "3. 출    금" << endl;
	cout << "4. 계좌정보 전체 출력" << endl;
	cout << "5. 프로그램 종료" << endl;
}

void MakeAccount(void) {
	int id;
	char name[NAME_LEN];
	int balance;

	cout << "[계좌개설]" << endl;
	cout << "계좌ID: ";	cin >> id;
	cout << "이  름: ";	cin >> name;
	cout << "입금액: ";	cin >> balance;
	cout << endl;

	accArr[accNum++] = new Account(id, balance, name);
}

void 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 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 ShowAllAccInfo(void) {
	for (int i = 0; i < accNum; i++)
	{
		accArr[i]->ShowAccInfo();
		cout << endl;
	}
}

0.3 버전과 다른점 : 아래 코드 부분이 추가됨
-> const 선언을 추가해서 코드의 안정성과 완성도를 조금 더 높였다.

int GetAccID() const { return accID; }

void ShowAccInfo() const {
		cout << "계좌ID: " << accID << endl;
		cout << "이  름: " << cusName << endl;
		cout << "잔  액: " << balance << endl;
	}

friend

  • A 클래스가 B 클래스를 대상으로 friend 선언을 하면, B클래스는 A 클래스의 private 멤버에 직접 접근 가능하다.

  • friend 선언은 정보 은닉 을 무너뜨리는 문법이기 때문에 조심히 사용하자
    전역함수를 대상으로도, 클래스의 멤버함수를 대상으로도 friend 선언이 가능하다.

  • friend로 선언된 함수는 자신이 선언된 클래스의 private 영역에 접근 가능하다.

static 멤버 변수

  • 전역변수에 선언된 static: 선언된 파일 내에서만 참조를 허용하겠다는 의미

  • 함수 내에 선언된 static: 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않는다.

  • static 멤버변수는 클래스 변수라고도 한다. 일반적인 멤버변수와 달리 클래스당 하나씩만 생성되기 때문이다.

  • 객체 내부에 static 멤버변수가 있는것이 아니라 객체 외부에 있다. 다만 객체에게 멤버변수처럼 접근할 수 있는 권한을 줬을 뿐이다.

  • 이로 인해 객체가 생성되던 생성 되있지 않던, 항상 class명으로 접근 가능하다.

  • public으로 선언되면 클래스의 이름 또는 객체의 이름을 통해서 어디서든 접근 가능하다.

  • public static 멤버변수를 객체를 통해 멤버변수에 접근하듯이 접근하면 static 변수가 아닌 일반 멤버변수로 접근 하는 것처럼 보이니 지양하자.

static 멤버 함수

기본적으로 그 특성이 static 멤버변수와 동일하다.

  • 선언된 클래스의 모든 객체가 공유한다.

  • public으로 선언이 되면, 클래스의 이름을 이용해서 호출이 가능하다.

  • 객체의 멤버로 존재하는 것이 아니다.

"static 멤버함수 내에서는 static 멤버변수와 static 멤버함수만 호출이 가능하다"

이러한 static 멤버변수와 static 멤버함수를 통해 전역변수와 전역함수를 대체할 수 있다.

const static

  • 클래스 내에 선언된 const 멤버변수(상수)의 초기화는 이니셜라이저를 통해야만 한다. 그러나 const static으로 선언되는 멤버변수(상수)는 다음과 같이 선언과 동시에 초기화가 가능하다.
class CountryArea{
public:
	const static int RUSSIA =1707540;
   const static int CANADA = 123909;
   const static int KOREA = 12387;
   const static int CHINA = 2984719;
};
  • 이렇듯 const static 상수는 하나의 클래스에 둘 이상 모이는 것이 보통이다.

  • 이렇게 정의된 상수에 접근하기 위해 굳이 객체를 생성할 필요는 없다. 이렇듯 클래스의 이름을 통해서 접근하는 것이 편하기도 하고, 접근하는 대상에 대한 정보를 쉽게 노출하는 방법이 되기도 한다.

  • const static 멤버변수는, 클래스가 정의될 때(객체가 생성될때가 아님) 지정된 값이 유지되는 상수이기 때문에, 위 예제에서 보이는 바와 같은 방법으로 초기화가 가능하도록 문법으로 정의하고 있다.

const

const 로 선언된 함수는 const 객체를 대상으로 호출이 가능하다.
멤버변수에 저장된 값을 수정하지 않는 함수는 가급적 const로 선언한다.
const 함수도 오버로딩이 가능하다.

C++ 복사생성자, Friend, const, static(저장용,메모용, 윤성우 열혈 C++ 프로그래밍 정리 CH 5,6)

0개의 댓글

관련 채용 정보