버전 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;
}
A 클래스가 B 클래스를 대상으로 friend 선언을 하면, B클래스는 A 클래스의 private 멤버에 직접 접근 가능하다.
friend 선언은 정보 은닉 을 무너뜨리는 문법이기 때문에 조심히 사용하자
전역함수를 대상으로도, 클래스의 멤버함수를 대상으로도 friend 선언이 가능하다.
friend로 선언된 함수는 자신이 선언된 클래스의 private 영역에 접근 가능하다.
전역변수에 선언된 static: 선언된 파일 내에서만 참조를 허용하겠다는 의미
함수 내에 선언된 static: 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않는다.
static 멤버변수는 클래스 변수라고도 한다. 일반적인 멤버변수와 달리 클래스당 하나씩만 생성되기 때문이다.
객체 내부에 static 멤버변수가 있는것이 아니라 객체 외부에 있다. 다만 객체에게 멤버변수처럼 접근할 수 있는 권한을 줬을 뿐이다.
이로 인해 객체가 생성되던 생성 되있지 않던, 항상 class명으로 접근 가능하다.
public으로 선언되면 클래스의 이름 또는 객체의 이름을 통해서 어디서든 접근 가능하다.
public static 멤버변수를 객체를 통해 멤버변수에 접근하듯이 접근하면 static 변수가 아닌 일반 멤버변수로 접근 하는 것처럼 보이니 지양하자.
기본적으로 그 특성이 static 멤버변수와 동일하다.
선언된 클래스의 모든 객체가 공유한다.
public으로 선언이 되면, 클래스의 이름을 이용해서 호출이 가능하다.
객체의 멤버로 존재하는 것이 아니다.
"static 멤버함수 내에서는 static 멤버변수와 static 멤버함수만 호출이 가능하다"
이러한 static 멤버변수와 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 함수도 오버로딩이 가능하다.
C++ 복사생성자, Friend, const, static(저장용,메모용, 윤성우 열혈 C++ 프로그래밍 정리 CH 5,6)