[C++8] 정보은닉

모옹·2023년 12월 21일
0

C++

목록 보기
8/10
post-thumbnail

8-1. 정보은닉

정보 은닉
멤버 변수를 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으로 아무나 접근 가능하게 되어 있다.


8-2. const 함수

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;
}

8-3. Example

위의 내용을 참고해서 7번 글의 과일 판매 코드를 아래 조건들을 넣어 수정해보았다. (맞는지는 모르겠다..)

  • 사과의 구매를 목적으로 0보다 작은 수를 전달할 수 없다.
  • 사과를 가진 돈 보다 많이 구매할 수 없다.
  • 사과를 판매 재고보다 많이 구매할 수 없다.
  • 사과의 판매 가격을 0원 보다 작게 설정할 수 없다.

8-3-1. 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

8-3-2. 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;
}

8-3-3. 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++ 프로그래밍>
위 책을 공부하며 정리한 내용입니다.

0개의 댓글