정보 은닉
멤버 변수를 private로 선언하고, 해당 변수에 접근하는 함수(access function)를 별도로 정의해서 안전한 형태로 멤버 변수의 접근을 유도하는 것
아래 코드의 문제점이 무엇일까?
#include<iostream>
using namespace std;
class Point{
public:
int x; // 0 <= x <= 100
int y; // 0 <= y <= 100
};
class Rectangle{
public:
Point upLeft;
Point lowRight;
};
int main(void)
{
Point pos1={-2, 4};
Point pos2={5, 9};
Rectangle rec={pos2, pos1};
return 0;
}
// upLeft : [5, 9]
// lowRight : [-2, 4]
점의 좌표가 0 ~ 100 을 초과하기도 하고, 좌측 상단과 우측 하단이 바뀐 경우가 생겼다.
제한된 방법으로의 접근만 허용해서 잘못된 값이 저장되지 않도록 하고, 실수가 발생하더라도 쉽게 발견될 수 있도록 해야 한다.
위에서는 x, y 값이 public으로 아무나 접근 가능하게 되어 있다.
const 함수
함수 내에서 멤버 변수에 저장된 값을 변경하지 않겠다고 선언하는 것
프로그래머가 실수로 자신의 의도와는 다르게 멤버변수의 값을 변경했을 때, 컴파일 에러가 난다.
또한 const가 아닌 함수는 멤버변수에 저장된 값을 변경할 수 있는 여지가 있으므로, const 함수 내에서는 const 함수의 호출만 가능하다.
아래에서는 멤버 변수를 private로 선언하고, 해당 변수에 접근하는 함수(access function)를 별도로 정의해서 안전한 형태로 멤버 변수의 접근을 유도하고 있다.
Point.h
#ifndef __POINT_H_
#define __POINT_H_
class Point
{
private:
int x;
int y;
public:
bool InitMembers(int xpos, int ypos);
int GetX() const;
int GetY() const;
bool SetX(int xpos);
bool SetY(int ypos);
};
#endif
Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;
bool Point::InitMembers(int xpos, int ypos){
if(xpos<0 || ypos<0){
cout << "지정 범위를 벗어난 값이 전달됨" << endl;
return false;
}
x=xpos;
y=ypos;
return true;
}
int Point::GetX() const {
return x;
}
int Point::GetY() const {
return y;
}
bool Point::SetX(int xpos){
if(0>xpos || xpos>100){
cout << "지정 범위를 벗어난 값이 전달됨" << endl;
return false;
}
x=xpos;
return true;
}
bool Point::SetY(int ypos){
if(0>ypos || ypos>100){
cout << "지정 범위를 벗어난 값이 전달됨" << endl;
return false;
}
y=ypos;
return true;
}
위의 내용을 참고해서 7번 글의 과일 판매 코드를 아래 조건들을 넣어 수정해보았다. (맞는지는 모르겠다..)
FruitSale.h
#ifndef __FRUITSALE_H__
#define __FRUITSALE_H__
class FruitSeller
{
private:
int APPLE_PRICE;
int numOfApples;
int myMoney;
public:
bool InitMembers(int price, int num, int money);
bool SetPrice(int price);
int SaleApples(int money);
// 판매할 수 없는 수량의 사과를 요청받았을 경우에 대응하기 위함
bool CheckNum(int num);
void ShowSalesResult() const;
int GetMoney() const;
int GetNum() const;
};
class FruitBuyer
{
private:
int myMoney;
int numOfApples;
public:
bool InitMembers(int money);
bool SetMoney(int money);
void ShowBuyResult() const;
void BuyApples(FruitSeller &seller, int money);
int GetMoney() const;
int GetNum() const;
};
#endif
FruitSale.cpp
#include <iostream>
#include "FruitSale.h"
using namespace std;
bool FruitBuyer::InitMembers(int money){
if(money < 0){
cout << "0보다 작은 수가 전달되었습니다.\n";
return false;
}
myMoney = money;
return true;
}
bool FruitBuyer::SetMoney(int money){
if(money < 0){
cout << "0보다 작은 수가 전달되었습니다.\n";
return false;
}
myMoney = money;
return true;
}
int FruitBuyer::GetMoney() const {
return myMoney;
}
int FruitBuyer::GetNum() const {
return numOfApples;
}
void FruitBuyer::ShowBuyResult() const {
cout << "구매 후 보유 금액 : " << GetMoney() << endl;
cout << "구매한 사과 개수 : " << GetNum() << endl;
}
void FruitBuyer::BuyApples(FruitSeller &seller, int money){
if(money < 0){
cout << "사과를 0원 보다 적게 구매할 수 없습니다.\n";
return;
}
if(myMoney - money < 0){
cout << "해당 수량을 구매할 예산이 부족합니다.\n";
return;
}
int now_buying = seller.SaleApples(money);
if(now_buying == -1) {
cout << "해당 수량만큼 구매할 수 없습니다.\n";
return;
}
numOfApples += now_buying;
myMoney -= money;
}
bool FruitSeller::InitMembers(int price, int num, int money){
if(num < 0){
cout << "판매할 수 있는 사과의 개수가 0보다 작습니다.\n";
return false;
}
if(price < 0){
cout << "사과의 가격은 0원 보다 작을 수 없습니다.\n";
return false;
}
APPLE_PRICE = price;
numOfApples = num;
myMoney = money;
return true;
}
int FruitSeller::SaleApples(int money) {
int num = money / APPLE_PRICE;
if(CheckNum(num)){ // 재고가 구매 요청 수량보다 많은 경우
myMoney += money;
return num;
};
return -1; // 재고 부족
}
bool FruitSeller::SetPrice(int price){
if(price < 0){
cout << "사과의 가격이 0보다 작게 전달되었습니다.\n";
return false;
}
APPLE_PRICE = price;
return true;
}
bool FruitSeller::CheckNum(int num){
if(num < 0){
cout << "판매할 수 있는 수량이 아닙니다.\n";
return false;
}
numOfApples = num;
return true;
}
int FruitSeller::GetMoney() const {
return myMoney;
}
int FruitSeller::GetNum() const {
return numOfApples;
}
void FruitSeller::ShowSalesResult() const {
cout << "남은 사과의 개수 : " << GetNum() << endl;
cout << "현재 보유 금액 : " << GetMoney() << endl;
}
main.cpp
#include <iostream>
#include "FruitSale.h"
using namespace std;
int main(void){
FruitSeller seller;
seller.InitMembers(1000, 20, 0);
FruitBuyer buyer1;
buyer1.InitMembers(5000);
buyer1.BuyApples(seller, 2000);
seller.SetPrice(-500); // 음의 가격 설정 불가능
buyer1.BuyApples(seller, 100000); // 예산 초과
FruitBuyer buyer2;
buyer2.InitMembers(200000);
buyer2.BuyApples(seller, 200000); // 재고 부족
cout<<"판매 내역"<<endl;
seller.ShowSalesResult();
cout<<"1번 구매자의 구매 내역"<<endl;
buyer1.ShowBuyResult();
cout<<"2번 구매자의 구매 내역"<<endl;
buyer2.ShowBuyResult();
return 0;
}
<출처 : 윤성우의 열혈 C++ 프로그래밍>
위 책을 공부하며 정리한 내용입니다.