[열혈 C++] Chap04 연습문제
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++ 규격인지는 모르겠다.
-