C & C++/디딤돌 C++

[C++] 74. 최종 실습 – 클래스 추가하기

언휴 2024. 4. 19. 10:59
[C++] 최종 실습 – 클래스 추가하기

이제 클래스를 추가하고 클래스 사이의 관계에 따라 헤더 파일을 포함합시다. 여기에서는 헤더 파일에 포함문을 작성하는 것 까지만 할 거예요.

C++ 최종 실습 – 클래스 다이어그램

클래스 다이어그램을 보면서 클래스를 추가하세요. 현재 EhNara, Place, Downtown, School, Village 클래스를 추가한 상태죠. 앞에서 작성한 확장 가능한 순차 배열인 SeqArray 템플릿 클래스를 추가하세요. 그리고 상속과 다형성 최종 실습에서 작성한 프로그램에서 Student, MStudent, SStudent, PStudent 클래스를 이용할게요. 소스 파일과 헤더 파일을 복사하여 프로젝트에 추가하세요.

이 외에 Man, IStudy, IRelax, IPlay를 추가하세요. 그리고 이를 기반으로 Student 클래스를 추가하세요. 그리고 Student 클래스를 기반으로 MStudent, SStudent, PStudent 클래스를 추가하세요. StuFactory 클래스와 IComeBack도 추가하세요. 그리고 IComeBack을 기반으로 파생 형식으로 EhNara를 변경하세요.

이제 포함문을 작성합니다. EhNara에서는 StuFactory에 명령을 내려야 하므로 StuFactory.h 를 포함하세요. 그리고 학생을 보관해야 하므로 Student.h 파일을 포함하세요.

Place 클래스에서는 IComeBack에 명령을 내릴 수 있게 IComeBack.h를 포함하세요. 그리고 Man을 보관해야 하므로 Man.h 도 포함하세요. StuFactory 또한 Student를 포함하세요. 그리고 IComeBack에서는 사람을 복귀할 수 있어야 하므로 Man.h를 포함하세요.

그리고 학교에서는 학사 학생과 IStudy, 주거지에서는 마법학생과 IRelax, 다운타운에서는 운동학생과 IPlay에게 명령을 내릴 수 있어야 하므로 이에 맞게 헤더 파일을 포함하세요.

EhNara, Place, StuFactory에서는 컬렉션이 필요하므로 SeqArray.h를 포함하세요.

제약 조건에 Student의 생성과 소멸은 StuFactory에서만 가능하게 구현해야 합니다. 이를 위해 Student의 생성자와 소멸자를 protected로 접근 지정을 한정하고 friend class로 StuFactory로 설정하세요. protected로 접근 지정하는 이유는 파생 형식이 만들어지는 과정에 기반 형식의 생성자를 호출하기 때문에 최소 접근 지정을 protected로 해 주어야 합니다. 그리고 다른 형식에서 접근할 수 없게 하기 위해 protected로 한 것입니다.

또한 friend는 상속의 대상이 아니므로 MStudent, PStudent, SStudent의 생성자와 소멸자의 가시성도 private으로 접근 지정하세요.

이처럼 설정하면 StuFactory에서도 개체 생성을 할 수 없어서 StuFactory를 friend class 로 설정한 것입니다. friend를 사용하면 자신의 은폐한 모든 멤버를 friend로 지정한 곳에서는 가시성이 생겨 정보 은닉의 장점이 부분적으로 사라집니다. 여러분께서 friend를 사용하 때는 전체의 신뢰성을 높이기 위해 가시성을 낮추고 반드시 필요한 곳에 부분적으로 가시성을 주기 위해 사용하세요.

현재까지 작성한 내용은 다음과 같습니다.

//IComeBack.h
#pragma once
#ifndef interface
#define interface struct
#endif
#include "Man.h"
interface IComeBack
{
};
//IPlay.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IPlay
{   
};
//IRelax.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IRelax
{   
};
//IStudy.h
#pragma once
#ifndef interface
#define interface struct
#endif
interface IStudy
{   
};
//ehglobal.h
#pragma once
enum keydata //기능 키에 사용할 상수 열거
{
    NO_DEFINED,F1,F2,F3,F4,F5,F6,F7,F8, ESC
}; 
class ehglobal
{
public:
    static void clrscr();         //콘솔 화면 클리어
    static keydata getkey();   //기능 키 입력
    static void waitkey(); //아무 키나 누를 때까지 대기
private:
    ehglobal(void) {    }
    ~ehglobal(void) {    }
};
//ehglobal.cpp
#include "ehglobal.h" 
#include <conio.h>
#include <windows.h> 
void ehglobal::clrscr()
{
    system("cls");    
}
keydata ehglobal::getkey()
{
    int key = getch();
    if(key == 27)//key가 27이면 ESC를 누른 것입니다.
    {
        return ESC;
    }
    if(key == 0) //key가 0이면 기능 키를 누른 것입니다.
    {
        key = getch();//다시 한 번 getkey를 호출해야 합니다.
        switch(key)//key의 값에 따라 기능 키를 정의한 열거형의 상수를 반환합니다.
        {
        case 59: return F1;  case 60: return F2;    case 61: return F3;   case 62: return F4;
        case 63: return F5;  case 64: return F6;    case 65: return F7;   case 66: return F8;
        }
    }
    return NO_DEFINED;
}
void ehglobal::waitkey()
{
    getkey();
}
//SeqArray.h
#pragma once
template <typename data>
class SeqArray
{
    data *base; //저장소
    size_t capacity; //저장소 크기
    size_t size; //보관 개수
public:
    SeqArray()
    {
        base = 0;
        capacity = 0;
        size = 0;
    }
    ~SeqArray(void)
    {
        if(base)//저장소가 있을 때
        {
            delete[] base;//저장소 해제
        }
    }
    void PushBack(data value)//순차 보관
    {
        if(IsFull())//꽉차면
        {
            if(capacity)//저장소의 개수가 참일 때
            {
                Reserve(capacity *2);//두 배로 확장
            }
            else//아닐 때(0일 때)
            {
                Reserve(1);//1로 확장
            }
        }
        base[size] = value;//보관
        size++;//보관 개수 1 증가
    }
    void RemoveAt(size_t index)//특정 인덱스 요소 삭제
    {
        if(IsAvailIndex(index)==false)//인덱스가 유효하지 않을 때
        {
            return;
        }
        size--;//보관 개수 1 감소
        for(   ;index<size;index++)
        {
            base[index] = base[index+1];//한 칸씩 앞으로 이동
        }
    }
    template <typename find_if>
    int FindIf(find_if fun)//특정 알고리즘이 처음으로 참인 위치 찾기
    {
        for(size_t i = 0; i<size; ++i)
        {
            if(fun(base[i]))//알고리즘에 적용하였을 때 참이면
            {
                return i; //인덱스 반환
            }
        }
        return -1;//-1 반환
    }
    data &operator[](size_t index)//인덱서
    {
        if(IsAvailIndex(index)==false)//유효하지 않은 인덱스일 때
        {
            throw "유효하지 않은 인덱스를 사용하였습니다.";//예외 던짐
        }
        return base[index];//인덱스의 원소 반환
    }
    bool IsAvailIndex(size_t index)const//유효한 인덱스인지 판별
    {
        return (index>=0)&&(index<size);
    }
    size_t GetSize()const
    {
        return size;
    }

private:
    bool IsFull()const//꽉 찼는지 판별
    {
        return size == capacity;
    }
    void Reserve(int ncapacity)//저장소 확장
    {
        data *tbuf = base;//저장소 위치를 tbuf로 설정
        base = new data[ncapacity];//저장소 동적 할당
        capacity = ncapacity;//저장소 크기 설정
        if(tbuf)//이전 저장소가 참이면
        {
            for(size_t i=0; i<size;++i)
            {
                base[i] = tbuf[i];//이전 저장소에 보관한 값을 새로운 저장소로 이동
            }
            delete[] tbuf;//이전 저장소 메모리 해제
        }
    }
};
//Man.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Man
{
public:
    Man(void);
    ~Man(void);
};
//Man.cpp
#include "Man.h"

Man::Man(void)
{
}
Man::~Man(void)
{
}
//StuConst.h
#pragma once
class StuConst
{
public:
    static const int def_iq;
    static const int max_iq;
    static const int min_iq;

    static const int def_hp;
    static const int max_hp;
    static const int min_hp;

    static const int def_stress;
    static const int max_stress;
    static const int min_stress;

    static const int def_scnt;
    static const int max_scnt;
    static const int min_scnt;
    
private://개체를 생성할 수 없게 함
    StuConst(void);    
};
//StuConst.cpp
#include "StuConst.h"
const int StuConst::def_iq = 100;
const int StuConst::max_iq=200;
const int StuConst::min_iq=0;             
const int StuConst::def_hp=100;
const int StuConst::max_hp=200;
const int StuConst::min_hp=0;             
const int StuConst::def_stress=0;
const int StuConst::max_stress=100;
const int StuConst::min_stress=0;             
const int StuConst::def_scnt=0;
const int StuConst::max_scnt=5;
const int StuConst::min_scnt=0;
StuConst::StuConst(void)
{
}
//Student.h
#pragma once
#include "Man.h"
#include "IPlay.h"
#include "IRelax.h"
#include "IStudy.h"
#include "StuConst.h"

using namespace std;
class Student:public Man, public IStudy, public IRelax, public IPlay
{
    static int last_pn;
    const int pn;
    string name;
    int iq;
    int hp;
    int stress;
    int scnt;
public:    
    virtual void Study()=0;
    virtual void ListenLecture()=0;
    virtual void Sleep()=0;
    virtual void Relax()=0;
    virtual void Drink()=0;
    virtual void Sing()=0;
    virtual void View()const;
    int GetPN()const;
    string GetName()const;
    int GetIQ()const;
    int GetHP()const;
    int GetStress()const;
    int GetSCnt()const;
protected:
    Student(string name);
    void SetIQ(int iq);
    void SetHP(int hp);
    void SetStress(int stress);
    void SetSCnt(int scnt);    
};
//Student.cpp
#include "Student.h"
#define SC StuConst //간략하게 사용할 수 있게 매크로 정의

int Student::last_pn;
Student::Student(string name):pn(++last_pn)
{
    this->name = name;
    SetIQ(SC::def_iq);
    SetHP(SC::def_hp);    
    SetStress(SC::def_stress);
    SetSCnt(SC::def_scnt);
}
void Student::View()const
{
    cout<<"주민 번호:"<<pn<<" 이름:"<<name<<endl;
    cout<<"  IQ:"<<iq<<" HP:"<<hp<<" Stress:"<<stress<<endl;
    cout<<"  연속으로 공부한 횟수:"<<scnt<<endl;
}
int Student::GetPN()const
{
    return pn;
}
string Student::GetName()const
{
    return name;
}
int Student::GetIQ()const
{
    return iq;
}
int Student::GetHP()const
{
    return hp;
}
int Student::GetStress()const
{
    return stress;
}
int Student::GetSCnt()const
{
    return scnt;
}
void Student::SetIQ(int iq)
{
    if(iq>SC::max_iq)
    {
        iq = SC::max_iq;
    }

    if(iq<SC::min_iq)
    {
        iq = SC::min_iq;
    }
    this->iq = iq;
}

void Student::SetHP(int hp)
{
    if(hp>SC::max_hp)
    {
        hp = SC::max_hp;
    }

    if(hp<SC::min_hp)
    {
        hp = SC::min_hp;
    }
    this->hp = hp;
}

void Student::SetStress(int stress)
{
    if(stress>SC::max_stress)
    {
        stress = SC::max_stress;
    }

    if(stress<SC::min_stress)
    {
        stress = SC::min_stress;
    }
    this->stress = stress;
}


void Student::SetSCnt(int scnt)
{
    if(scnt>SC::max_scnt)
    {
        scnt = SC::max_scnt;
    }
    if(scnt<SC::min_scnt)
    {
        scnt = SC::min_scnt;
    }
    this->scnt = scnt;
}
//SStudent.h
#pragma once
#include "Student.h"
class SStudent :
    public Student
{
    int dummy;
    int total_scnt;
public:    
    virtual void Study();
    virtual void ListenLecture();
    virtual void Sleep();
    virtual void Relax();
    virtual void Drink();
    virtual void Sing();
    virtual void View()const;
    void Reading();
private:
    SStudent(string name);  
};
//SStudent..cpp
#include "SStudent.h"

SStudent::SStudent(string name):Student(name)
{
    dummy = 0;//더미 뇌는 생성 시 0
    total_scnt = 0;
}

void SStudent::Study()
{
    SetHP(GetHP()-5);//체력 5소모
    SetIQ(GetIQ()+GetSCnt()+dummy);//지력: scnt+더미 뇌 증가
    SetStress(GetStress()-2);//스트레스: 2감소
    SetSCnt(GetSCnt()+1);
    total_scnt++;

    if(total_scnt%5 == 0)//더미 뇌는 공부한 회수가 5의 배수가 될 때마다 1씩 증가
    {
        dummy++;
    }
}
void SStudent::ListenLecture()
{
    SetHP(GetHP()-3); //체력 3소모
    SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
    SetStress(GetStress()+GetSCnt());// 스트레스: scnt증가
    SetSCnt(0);
}
void SStudent::Sleep()
{
    SetHP(GetHP()+10); //체력 10회복    
    SetStress(GetStress()-5); //스트레스: 5감소
    SetSCnt(0);
}
void SStudent::Relax()
{
    SetHP(GetHP()+3); //체력 3회복    
    SetStress(GetStress()-25); //스트레스: 25감소
    SetSCnt(0);
}
void SStudent::Drink()
{
    SetHP(GetHP()+5); //체력 5회복
    SetIQ(GetIQ()-10);//지력:  10감소
    SetStress(GetStress()+2);//스트레스: 2증가
    SetSCnt(0);    
}
void SStudent::Sing()
{
    SetHP(GetHP()-10); //체력 10 소모
    SetIQ(GetIQ()-(5-GetSCnt()));//지력: 5-scnt감소
    SetStress(GetStress()+(5-GetSCnt()));//스트레스: 5-scnt증가
    SetSCnt(0);    
}
void SStudent::View()const
{
    cout<<"학사 학생";
    Student::View();
    cout<<" 더미 뇌:"<<dummy<<"연속으로 공부한 횟수:"<<total_scnt<<endl;
}
void SStudent::Reading()
{
    dummy++;//더미 뇌 1증가
    SetStress(GetStress()-5);//스트레스: 5감소
}
//MStudent.h
#pragma once
#include "Student.h"
class MStudent :
    public Student
{
    int stick;
public:    
    virtual void Study();
    virtual void ListenLecture();
    virtual void Sleep();
    virtual void Relax();
    virtual void Drink();
    virtual void Sing();
    virtual void View()const;
    void Travel();
private:
    MStudent(string name);
};
//MStudent.cpp
#include "MStudent.h"

MStudent::MStudent(string name):Student(name)
{
    stick=0;//지팡이는 생성 시 0
}

void MStudent::Study()
{    
    SetHP(GetHP()-3);//체력 3소모
    SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
    SetStress(GetStress()+3);//스트레스: 3증가
    SetSCnt(GetSCnt()+1);    
}
void MStudent::ListenLecture()
{
    SetHP(GetHP()-2); //체력 2소모
    SetIQ(GetIQ()+GetSCnt());//지력: scnt 증가
    SetStress(GetStress()+5);// 스트레스: 5증가
    SetSCnt(0);
}
void MStudent::Sleep()
{
    SetHP(GetHP()+10); //체력 10회복    
    SetStress(GetStress()-5); //스트레스: 5감소
    SetSCnt(0);
}
void MStudent::Relax()
{
    SetHP(GetHP()+3); //체력 3회복    
    SetStress(GetStress()-25); //스트레스: 25감소
    SetSCnt(0);
}
void MStudent::Drink()
{
    SetHP(GetHP()+5+stick); //체력 5+지팡이 회복
    SetIQ(GetIQ()-(10-stick));//지력:  10-지팡이 감소
    SetStress(GetStress()-2);//스트레스: 2감소
    SetSCnt(0);    
}
void MStudent::Sing()
{
    SetHP(GetHP()-(10-stick)); //체력 10-지팡이 소모
    SetIQ(GetIQ()-5);//지력: 5감소
    SetStress(GetStress()-5);//스트레스: 5감소
    SetSCnt(0);    
}
void MStudent::View()const
{
    cout<<"마법 학생";
    Student::View();
    cout<<" 지팡이:"<<stick<<endl;
}
void MStudent::Travel()
{
    stick++;//지팡이 1증가    
}
//PStudent.h
#pragma once
#include "Student.h"
class PStudent :
    public Student
{
    int air;
public:    
    virtual void Study();
    virtual void ListenLecture();
    virtual void Sleep();
    virtual void Relax();
    virtual void Drink();
    virtual void Sing();
    virtual void View()const;
    void Dance();
private:
    PStudent(string name);
};
//PStudent..cpp
#include "PStudent.h"
 
PStudent::PStudent(string name):Student(name)
{
    air=0;//air는 생성 시 0
}
void PStudent::Study()
{    
    SetHP(GetHP()-2);//체력 2소모
    SetIQ(GetIQ()+GetSCnt()/2);//지력: scnt/2 증가
    air-=3;
    SetStress(GetStress()-air*3);//스트레스: air*3감소
    SetSCnt(GetSCnt()+1);    
}
void PStudent::ListenLecture()
{
    SetHP(GetHP()-1); //체력 1소모
    SetIQ(GetIQ()+GetSCnt()/2);//지력: scnt/2 증가
    air-=5;
    SetStress(GetStress()-air*3);// 스트레스: air*3 감소
    SetSCnt(0);
}
void PStudent::Sleep()
{
    SetHP(GetHP()+10); //체력 10회복    
    SetStress(GetStress()-5); //스트레스: 5감소
    SetSCnt(0);
}
void PStudent::Relax()
{
    SetHP(GetHP()+8); //체력 8회복    
    SetStress(GetStress()-25); //스트레스: 25감소
    SetSCnt(0);
}
void PStudent::Drink()
{
    SetHP(GetHP()+5); //체력 5 회복
    SetIQ(GetIQ()-3);//지력:  3 감소
    SetStress(GetStress()-2);//스트레스: 2감소
    SetSCnt(0);    
}
void PStudent::Sing()
{
    SetHP(GetHP()-5); //체력 5 소모
    SetIQ(GetIQ()+2);//지력: 5증가
    SetStress(GetStress()-5);//스트레스: 5감소
    SetSCnt(0);    
}
void PStudent::View()const
{
    cout<<"운동 학생";
    Student::View();
    cout<<" air:"<<air<<endl;
}
void PStudent::Dance()
{    
    SetHP(GetHP()-5); //체력 5 소모
    SetIQ(GetIQ()+3);//지력: 3증가
    air++;//air 1증가    
}
//StuFactory.h
#pragma once
#include "SeqArray.h"
#include "Student.h"
class StuFactory
{
public:
    StuFactory(void);
    ~StuFactory(void);
};
//StuFactory.cpp
#include "StuFactory.h"
StuFactory::StuFactory(void)
{   
}
StuFactory::~StuFactory(void)
{   
}
//Place.h
#pragma once
#include "IComeBack.h"
#include "Man.h"
#include "SeqArray.h"
#include "ehglobal.h"
class Place
{
public:
    Place(void);
    ~Place(void);
    void Run();
protected:
    int SelectMenu();
    virtual void ViewMenu()const;
    void ComeBackStu();//학생 복귀
    virtual void DoItByKey(int key)=0;//키에 따라 기능 수행
};

//Place.cpp
#include "Place.h"

Place::Place(void)
{
}
Place::~Place(void)
{
}
void Place::Run()
{
    int key = 0;
    while((key = SelectMenu())!=ESC)
    {
        if(key == F1)
        {
            ComeBackStu();//학생 복귀
        }
        else
        {
            DoItByKey(key);//키에 따라 기능 수행
        }
        cout<<"아무 키나 누르세요."<<endl;
        ehglobal::getkey();
    }
}
int Place::SelectMenu()
{
    ehglobal::clrscr();
    ViewMenu();
    return ehglobal::getkey();
}
void Place::ViewMenu()const
{
    cout<<"ESC:초점 종료"<<endl;
    cout<<"F1: 이에이치 나라로 학생 "<<endl;
}
void Place::ComeBackStu()//학생 복귀
{
    cout<<"학생 복귀"<<endl;
}

//School.h
#pragma once
#include "Place.h"
#include "IStudy.h"
#include "SStudent.h"

class School :
    public Place
{
public:
    School(void);
    ~School(void);
private:
    virtual void ViewMenu()const;  //메뉴 출력
    virtual void DoItByKey(int key);//키에 따라 기능 수행        
    void StartLecture();//강의 시작
    void GoToLibrary();//도서관으로 가기
};
//School.cpp
#include "School.h"

School::School(void)
{
}
School::~School(void)
{
}
void School::ViewMenu()const  //메뉴 출력
{
    Place::ViewMenu();
    cout<<"F2: 강의 시작"<<endl;
    cout<<"F3: 도서관으로 가기"<<endl;
}
void School::DoItByKey(int key)//키에 따라 기능 수행
{
    switch(key)
    {
    case F2: StartLecture(); break; //강의 시작
    case F3: GoToLibrary(); break; //도서관으로 가기
    default: cout<<"잘못 선택하였습니다."<<endl;
    }
}
void School::StartLecture()//강의 시작
{
    cout<<"강의 시작"<<endl;
}
void School::GoToLibrary()//도서관으로 가기
{
    cout<<"도서관으로 가기"<<endl;
}
//Village.h
#pragma once
#include "Place.h"
#include "IRelax.h"
#include "MStudent.h"

class Village :
    public Place
{
public:
    Village(void);
    ~Village(void);
private:
    virtual void ViewMenu()const;  //메뉴 출력
    virtual void DoItByKey(int key);//키에 따라 기능 수행
    void TurnOff();//소등
    void GoToLivingRoom();//거실로 가기
};
//Village.cpp
#include "Village.h"

Village::Village(void)
{
}
Village::~Village(void)
{
}
void Village::ViewMenu()const  //메뉴 출력
{
    Place::ViewMenu();
    cout<<"F2: 소등"<<endl;
    cout<<"F3: 거실로 가기"<<endl;
}
void Village::DoItByKey(int key)//키에 따라 기능 수행
{
    switch(key)
    {
    case F2: TurnOff(); break; //강의 시작
    case F3: GoToLivingRoom(); break; //도서관으로 가기
    default: cout<<"잘못 선택하였습니다."<<endl;
    }
}
void Village::TurnOff()//소등
{
    cout<<"소등"<<endl;
}
void Village::GoToLivingRoom()//거실로 가기
{
    cout<<"거실로 가기"<<endl;
}
//Downtown.h
#pragma once
#include "Place.h"
#include "PStudent.h"
#include "IPlay.h"

class Downtown:
        public Place
{
public:
    Downtown(void);
    ~Downtown(void);
private:
    virtual void ViewMenu()const;  //메뉴 출력
    virtual void DoItByKey(int key);//키에 따라 기능 수행
    void Party();//파티
    void GoToSing();//노래방으로 가기
};
//Downtown.cpp
#include "Downtown.h"

Downtown::Downtown(void)
{
}
Downtown::~Downtown(void)
{
}
void Downtown::ViewMenu()const  //메뉴 출력
{
    Place::ViewMenu();
    cout<<"F2: 파티"<<endl;
    cout<<"F3: 노래방으로 가기"<<endl;
}
void Downtown::DoItByKey(int key)//키에 따라 기능 수행
{
    switch(key)
    {
    case F2: Party(); break; //파티
    case F3: GoToSing(); break; //노래방으로 가기
    default: cout<<"잘못 선택하였습니다."<<endl;
    }
}
void Downtown::Party()//파티
{
    cout<<"파티"<<endl;
}
void Downtown::GoToSing()//노래방으로 가기
{
    cout<<"노래방으로 가기"<<endl;
}
//EhNara.h
#pragma once
#include "SeqArray.h"
#include "StuFactory.h"
#include "IComeBack.h"
#include "Place.h"
#include "Student.h"

class EhNara:public IComeBack
{
    static EhNara app;//단일체
    enum PIndex//장소 인덱스
    {
        PI_SCHOOL, PI_DOWNTOWN, PI_VILLAGE, PI_MAX
    };

    Place *places[PI_MAX];
    
public:
    static void Start();//응용 시작 - 진입점에서 호출하는 정적 메서드
private:
    EhNara(void);
    ~EhNara(void);
    void Initialize(); //초기화
    void Run(); //사용자와 상호 작용
    void Exit(); //해제화

    int SelectMenu(); //메뉴 출력 및 선택
    void MakeStudent(); //학생 생성
    void MoveFocus(); //초점 이동
    void MoveStudent(); //학생 이동
    void ViewAll(); //전체 보기

    Place *SelectPlace();//장소 선택
};
//EhNara.cpp
#include "EhNara.h"
#include "School.h"
#include "Downtown.h"
#include "Village.h"
EhNara EhNara::app;//단일체
void EhNara::Start()//응용 시작 - 진입점에서 호출하는 정적 메서드
{
    app.Initialize();
    app.Run();
    app.Exit();
}
EhNara::EhNara(void){   }
EhNara::~EhNara(void){   }
void EhNara::Initialize()
{
    //장소 개체 생성
    places[PI_SCHOOL] = new School();
    places[PI_DOWNTOWN] = new Downtown();
    places[PI_VILLAGE] = new Village();
}


void EhNara::Run()
{
    int key = 0;
    while((key = SelectMenu())!=ESC)
    {
        switch(key)
        {
            case F1: MakeStudent(); break;
            case F2: MoveFocus();  break;
            case F3: MoveStudent(); break;
            case F4: ViewAll(); break;
            default: cout<<"잘못 선택하였습니다."<<endl; break;
        }
        cout<<"아무 키나 누르세요."<<endl;
        ehglobal::getkey();
    }
}
void EhNara::Exit() //해제화
{
    for(int i = 0; i<PI_MAX; i++)//모든 장소 개체 해제
    {
        delete places[i];
    }
}
int EhNara::SelectMenu() //메뉴 출력 및 선택
{
    ehglobal::clrscr();
    cout<<"이에이치 나라 메뉴"<<endl;
    cout<<"F1: 학생 생성 F2: 초점 이동 F3: 학생 이동 F4: 전체 보기 ESC: 프로그램 종료"<<endl;
    return ehglobal::getkey();
}
void EhNara::MakeStudent() //학생 생성
{
    cout<<"학생 생성"<<endl;
}
void EhNara::MoveFocus() //초점 이동
{
    Place *place = SelectPlace();//장소 선택
    if(place==0)
    {
        cout<<"잘못 선택하였습니다."<<endl;
        return;
    }
    place->Run();//장소의 상호 작용
}
void EhNara::MoveStudent() //학생 이동
{
    cout<<"학생 이동"<<endl;
}
void EhNara::ViewAll() //전체 보기
{
    cout<<"전체 보기"<<endl;
}
Place *EhNara::SelectPlace()//장소 선택
{
    cout<<"장소를 선택하세요."<<endl;
    cout<<"1: 학교 2: 다운타운 3: 주거지"<<endl;
    int pi=0;
    cin>>pi;
    if((pi<1)&&(pi>PI_MAX))//유효한 선택이 아닐 때
    {
        return 0;
    }
    return places[pi-1];
}
//Program.cpp
#include "EhNara.h"
int main()
{
    EhNara::Start();
    return 0;
}

여러분께서는 컴파일 및 빌드 후에 테스트를 해 보세요.