3 minute read

04-1. 정보은닉과 const

  • 코드💻
    /*
	4-1[정보은닉과 const]

	사과의 구매를 목적으로 0보다 작은 수를 전달할 수 없도록 하고, 
	안정성을 높일 수 있도록 const함수 선언해보자
    */

#include<iostream>
using namespace std;

class FruitSeller {
	private:
		int APPLE_PRICE;
		int numOfApples;
		int myMoney;

	public:
		void InitMembers(int price, int num, int money) {
			APPLE_PRICE = price;
			numOfApples = num;
			myMoney = money;
		}

		int saleApples(int money) {
			if (money < 0)      //0보다 작은 수가 전달되지 않도록 조건문을 달아줌
			{
				cout << "사과를 팔 수 없습니다. 판매를 종료합니다." << endl;
				return -1;
			}

			int num = money / APPLE_PRICE;
			numOfApples -= num;
			myMoney += money;
			return num;
		}

		void ShowSalesResult() const{		//이 함수 내에서는 변수 값을 바꿀 수 없음
			cout << "남은 사과: " << numOfApples << endl;
			cout << "판매 수익: " << myMoney << endl << endl;
		}		
};

class FruitBuyer {
	private:
		int myMoney;
		int numOfApples;

	public:
		void InitMembers(int money) {
			myMoney = money;
			numOfApples = 0;
		}

		int BuyApples(FruitSeller& seller, int money) {

			if (money < 0)  //0보다 작은 수가 전달되지 않도록 조건문을 달아줌
			{
				cout << "사과를 살 수 없어 구매를 종료합니다" << endl;
				return -1;
			}
				numOfApples += seller.saleApples(money);
				myMoney -= money;
		}

		void ShowBuyResult() const{   //이 함수 내에서는 변수 값을 바꿀 수 없음
			cout << "현재 잔액: " << myMoney << endl;
			cout << "사과 개수: " << numOfApples << endl << endl;
		}
};

int main(void) {
	FruitSeller seller;
	seller.InitMembers(1000, 20, 0);

	FruitBuyer buyer;
	buyer.InitMembers(5000);
	buyer.BuyApples(seller, 2000);

	cout << "과일 판매자의 현황" << endl;
	seller.ShowSalesResult();

	cout << "과일 구매자의 현황" << endl;
	buyer.ShowBuyResult();

	return 0;
}

04-2. 다양한 클래스의 정의/캡슐화

  • 코드💻
/*
    Point 클래스를 기반으로 원을 의미하는 Circle 클래스를 정의하자
    그리고 Circle 클래스를 기반으로 Ring 클래스를 정의하여 main 함수를 실행시키자.
*/
#include<iostream>
using namespace std;

class Point
{
private:
	int xpos;
	int ypos;

public:
	
	void Init(int x, int y) {
		xpos = x;
		ypos = y;
	}

	void ShowPointInfo() const {
		cout << "[" << xpos << "," << ypos << "]" << endl;
	}

};

class Circle
{
private:
	int r;		//반지름
	Point p;    //중심좌표

public:
	void Init(int x, int y, int r){
		p.Init(x, y);
		this->r = r;
	}

	void ShowCircleInfo() const {
		cout << "radius: " << r << endl;
		p.ShowPointInfo();
	}
		
};

class Ring
{
private:
	Circle c1;      //안쪽 원
	Circle c2;      //바깥쪽 원

public:
	void Init(int x1, int y1, int r1, int x2, int y2, int r2) {
		c1.Init(x1, y1, r1);
		c2.Init(x2, y2, r2);
	}
	
	void ShowRingInfo() const{
		cout << "Inner Circle Info..." << endl;
		c1.ShowCircleInfo();

		cout << "Outter Circle Info..." << endl;
		c2.ShowCircleInfo();
	}
};


int main(void) {
	Ring ring;
	ring.Init(1, 1, 4, 2, 2, 9);
	ring.ShowRingInfo();
	return 0;
}
  • Ring 클래스의 ShowRingInfo 함수에서는 Circle 클래스의 ShowCircleInfo 함수를 호출한다.
  • Circle 클래스의 ShowCircleInfo 함수에서는 Point 클래스의 ShowPointInfo 함수를 호출한다.

    즉, Ring 클래스, Circle 클래스, Point 클래스 모두 자신의 정보를 출력하기 위한 함수를 멤버에 포함시켜 캡슐화를 완성했다!

04-3. C++ 기반의 데이터 입출력

  • 코드💻
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

using namespace std;

namespace COMP_POS {
	enum 
	{
		CLERK, SENIOR, ASSIST, MANAGER
	};

	void ShowPositionInfo(int pos) {
		switch (pos)
		{
		case CLERK:
			cout << "직급: 사원" << endl;
			break;
		
		case SENIOR:
			cout << "직급: 주임" << endl;
			break;
		
		case ASSIST:
			cout << "직급: 대리" << endl;
			break;

		case MANAGER:
			cout << "직급: 과장" << endl;
			break;

		default:
			break;
		}
	}
}


class NameCard {
private:
	char* m_cpName;
	char* m_cpCom;
	char* m_cpPhone;
	int pos;

public:
	NameCard(const char * name, const char * company, const char * phone, int position);
	~NameCard();
	void ShowNameCard() const;
};

NameCard::NameCard(const char * name, const char* company, const char* phone, int position) 
{
	int len = strlen(name) + 1;
	m_cpName = new char[len];
	strcpy(m_cpName, name);

	len = strlen(company) + 1;
	m_cpCom = new char[len];
	strcpy(m_cpCom, company);

	len = strlen(phone) + 1;
	m_cpPhone = new char[len];
	strcpy(m_cpPhone, phone);

	pos = position;
}

void NameCard::ShowNameCard() const {
	cout << "이름: " << m_cpName << endl;
	cout << "회사: " << m_cpCom << endl;
	cout << "번호: " << m_cpPhone << endl;
	COMP_POS::ShowPositionInfo(pos);
	cout << endl;
}

NameCard::~NameCard() {
	delete[]m_cpName;
	delete[]m_cpCom;
	delete[]m_cpPhone;
}

int main(void) {

	NameCard man1("Lee", "Nike", "010-1234-1234", COMP_POS::CLERK);
	NameCard man2("Choi", "Kakao", "010-1004-1004", COMP_POS::SENIOR);
	NameCard man3("Park", "Samsung", "010-1588-1588", COMP_POS::MANAGER);

	man1.ShowNameCard();
	man2.ShowNameCard();
	man3.ShowNameCard();

	return 0;
}

  • ❗짚고 넘어갈 부분
    • 분명히 제대로 코딩한 것 같은데 계속 “해당 인수를 갖는 인스턴스를 찾을 수 없다”고 에러가 떴다. 실수했나 해서 답지도 봤는데 거의 똑같았다.

    • 알게 된 사실은 "Lee"은 문자열 상수인데, const가 선언되지 않은 포인터 형 char *으로 넘어가게 된다면 문제가 생긴다는 것이다. 상수라는 것은 컴파일 시에 고정되는 것으로 다시 바꿀 수 없는 특징이 있는데, const 문자열(문자열 상수)를 포인터로 참조하게 된다면 값을 바꿀 수 있는 가능성과 const의 보호가 충돌하게 된다.

    • 본인은 비주얼 스튜디오를 사용하고 있는데, 이 문제가 컴파일러의 문제인지 아니면 표준 C++ 규격인지는 모르겠다.

Tags: ,

Categories:

Updated: