I'm FanJae.

[C++ 기본 연습 문제] Chapter 04. 클래스의 완성 본문

C++/Basic Practice

[C++ 기본 연습 문제] Chapter 04. 클래스의 완성

FanJae 2024. 9. 4. 01:00

1. Chapter 04. 클래스의 완성

1-1. 정보은닉과 const

① - Chapter 03에서 제시한 과일장수 시뮬레이션 예제 FruitSaleSim1.cpp에서 정의한 두 클래스의 멤버변수는 private으로 선언이 되어있다. 그러나 다음 조건을 유지할 수 있는 장치는 아무것도 되어있지 않다.
- 사과의 구매를 목적으로 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 SaleAppples(int money)
    {
        if (money < 0)
        {
            std::cout << "0보다 작은 수는 전달할 수 없습니다." << std::endl;
            return 0;
        }
        int num = money / APPLE_PRICE;
        numOfApples -= num;
        myMoney += money;
        return num;
    }

    void ShowSaleResult() const
    {
        cout << "남은 사과: " << numOfApples << endl;
        cout << "판매 수익: " << myMoney << endl << endl;
    }

};

// 과일소비자 클래스
class FruitBuyer
{
private:
    int myMoney;
    int numOfApples;

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

    void BuyApples(FruitSeller& seller, int money)
    {
        if (money < 0)
        {
            std::cout << "0보다 작은 수는 전달할 수 없습니다." << std::endl;
            return ; 
        }
        numOfApples += seller.SaleAppples(money);
        myMoney -= money;
    }

    void ShowBuyResult() const
    {
        cout << "현재 잔액: " << myMoney << endl;
        cout << "사과 개수: " << numOfApples << endl << endl;
    }

};

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

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

    cout << "과일 판매자의 현황 " << endl;
    seller.ShowSaleResult();
    cout << "과일 구매자의 현황 " << endl;
    customer.ShowBuyResult();

    return 0;
}

- 출력만을 담당하는 함수들에는 모두 const 함수로 만들어준다.

- 사과를 판매 및 구매하는 함수에만 0보다 작은 수를 입력하지 못하게 처리해준다.

 

1-2. 다양한 클래스의 정의

- 다음의 Point 클래스를 기반으로 하여(활용하여) 원을 의미하는 Circle 클래스를 정의하자

class Point
{
private:
        int xpos, ypos;
public:
        void Init(int x, int y)
        {
               xpos = x;
               ypos = y;
        }
        void ShowPointInfo() const
        {
        cout << "[" << xpos << ", " << xpos << "]" << endl;
        }
};


 - Circle 객체에는 좌표상의 위치정보(원의 중심좌표)와 반지름의 길이 정보를 저장 및 출력할 수 있어야 한다.
- 그리고 여러분이 정의한 Circle 클래스를 기반으로 Ring 클래스도 정의하자.
- 링은 두개의 원으로 표현 가능하므로(바깥쪽 원과 안쪽 원), 두 개의 Circle 객체를 기반으로 정의가 가능하다.
다음 main 함수를 기반으로 실행시키자

int main(void)
{
        Ring ring;
        ring.Init(1, 1, 4, 2, 2, 9);
        ring.ShowRingInfo();
        return 0;
}

 

- Init 함수호출을 통해서 전달된 1, 1, 4는 안쪽 원의 정보에 해당하며(순서대로 X, Y, 반지름)
- 이어서 전달된 2, 2, 9는 바깥쪽 원의 정보에 해당한다(순서대로 X, Y, 반지름)

#include <iostream>
class Point
{
private:
    int xpos, ypos;
public:
    void Init(int x, int y)
    {
        xpos = x;
        ypos = y;
    }
    void ShowPointInfo() const
    {
        std::cout << "[" << xpos << ", " << xpos << "]" << std::endl;
    }
};

class Circle
{
private:
    Point x;
    int radius;
public:
    void Init(int x1, int y1, int rad1)
    {
        x.Init(x1, y1);
        radius = rad1;
    }
    void CircleInfo() const
    {
        std::cout << "radius: " << radius << std::endl;
        x.ShowPointInfo();
    }
    int getradius()
    {
        return radius;
    }
};

class Ring
{
private:
    Circle first;
    Circle second;
public:
    void Init(int x1, int y1, int rad1, int x2, int y2, int rad2) 
    {
        first.Init(x1, y1, rad1);
        second.Init(x2, y2, rad2);
    }
    void ShowRingInfo() const
    {
        std::cout << "Inner Circle Info... " << std::endl;
        first.CircleInfo();
        std::cout << "Outter Circle Info... " << std::endl;
        second.CircleInfo();
    }
};

int main(void)
{
    Ring ring;
    ring.Init(1, 1, 4, 2, 2, 9);
    ring.ShowRingInfo();
    return 0;
}

 

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

①  - 앞서 제시한 문제 4-2 해결하였는가? 당시만 해도 생성자를 설명하지 않은 상황이기 때문에 별도의 초기화
함수를 정의  호출해서 Point, Circle, Ring 클래스의 객체를 초기화 하였다.
  구현한 답에 대해서 모든 클래스에 생성자를 정의해보자

#include <iostream>
class Point
{
private:
    int xpos, ypos;
public:
    Point(int x, int y) : xpos { x }, ypos{ y } {  }
    void ShowPointInfo() const
    {
        std::cout << "[" << xpos << ", " << xpos << "]" << std::endl;
    }
};

class Circle
{
private:
    Point x;
    int radius;
public:
    Circle(int x1, int y1, int rad1) : x{ x1,y1 }, radius{ rad1 } { }
    void CircleInfo() const
    {
        std::cout << "radius: " << radius << std::endl;
        x.ShowPointInfo();
    }
    int getradius()
    {
        return radius;
    }
};

class Ring
{
private:
    Circle first;
    Circle second;
public:
    Ring(int x1, int y1, int rad1, int x2, int y2, int rad2) : first{ x1,y1,rad1 }, second{ x2,y2,rad2 } { }
    void ShowRingInfo() const
    {
        std::cout << "Inner Circle Info... " << std::endl;
        first.CircleInfo();
        std::cout << "Outter Circle Info... " << std::endl;
        second.CircleInfo();
    }
};

int main(void)
{
    Ring ring(1,1,4,2,2,9);
    ring.ShowRingInfo();
    return 0;
}

 

② 명함을 의미하는 NameCard 클래스를 정의해보자. 이 클래스에는 다음의 정보가 저장되어야 한다.
1.성명
2.회사이름
3.전화번호
4.직급

- 단, 직급 정보를 제외한 나머지는 문자열의 형태로 저장을 하되, 길이에 딱 맞는 메모리 공간을 할당 받는 형태로 정의하자. 그리고 직급 정보는 int형 멤버변수를 선언해서 저장을 하되, 아래의 enum 선언을 활용해야 한다
enum{CLERK, SENIOR, ASSIST, MANAGER};
위의 enum 선언에서 정의된 상수는 순서대로 사원, 주임, 대리, 과장을 뜻한다.

그럼 다음 main 함수와 실행의 예를 참조하여, 이 문제에서 원하는 형태대로 NameCard 클래스를 완성해보자

int main(void)
{
        NameCard manClerk("Lee", "ABCEng", "010-1111-2222", COMP_POS::CLERK);
        NameCard manSENIOR("Hong", "OrangeEng", "010-3333-4444", COMP_POS::SENIOR);
        NameCard manAssist("Kim", "SoGoodComp", "010-5555-6666", COMP_POS::ASSIST);
        manClerk.ShowNameCardInfo();
        manSENIOR.ShowNameCardInfo();
        manAssist.ShowNameCardInfo();
        return 0;
}

#include <iostream>
#include <string>
namespace COMP_POS
{
	enum { CLERK, SENIOR, ASSIST, MANAGER };
	void ShowPositionInfo(int pos)
	{
		switch (pos)
		{
		case CLERK:	std::cout << "사원" << std::endl; break;
		case SENIOR:	std::cout << "주임" << std::endl; break;
		case ASSIST:	std::cout << "대리" << std::endl; break;
		case MANAGER:	std::cout << "과장" << std::endl; break;
		}
	}
}

class NameCard
{
private:
	std::string name;
	std::string company;
	std::string phone;
	int position;

public:
	NameCard(std::string name, std::string company, std::string phone, int position) : name{ name }, company{ company }, phone{ phone }, position{ position }
	{

	}

	void ShowNameCardInfo() const
	{
		std::cout << "이름 : " << name << std::endl;
		std::cout << "회사 : " << company << std::endl;
		std::cout << "전화번호 : " << phone << std::endl;
		std::cout << "직급 : ";
		COMP_POS::ShowPositionInfo(position);
		std::cout << std::endl;
	}
};

int main(void)
{
	NameCard manClerk("Lee", "ABCEng", "010-1111-2222", COMP_POS::CLERK);
	NameCard manSENIOR("Hong", "OrangeEng", "010-3333-4444", COMP_POS::SENIOR);
	NameCard manAssist("Kim", "SoGoodComp", "010-5555-6666", COMP_POS::ASSIST);
	manClerk.ShowNameCardInfo();
	manSENIOR.ShowNameCardInfo();
	manAssist.ShowNameCardInfo();
	return 0;
}
Comments