C++ 과제: Virtual Function in Inheritance

3 분 소요

질문

내용

다음의 상속 계층도를 참조하여 화면에서 student, salesman, housewife의 선택에 따라 파생 클래스의 가상 함수 behavior()가 수행되도록 프로그램을 작성하시오.

inheritance

답변

내용

이 문제는 상속 계층도에서 클래스명, 함수명, 함수 내용 등 모든 조건이 사전에 주어져 있으므로 비교적 쉽게 풀이가 가능하다.

먼저 문제에 주어진 상속 계층도 내의 behavior 함수에서 출력 구문이 존재하므로 이와 관련 있는 헤더파일(iostream)을 선언하고, 편의를 위해 이름 공간인 std도 사용하자.

즉,

#include <iostream>

using namespace std;

이제 person 클래스를 작성해보자.

위 문제의 상속 계층도를 확인해보면, person 클래스 내에 behavior이라는 가상 함수(Virtual Function)가 존재한다.

그러므로 다음과 같이 코드를 작성해주자.

class person {
    public:
        virtual void behavior() {};
};

그 후 person 클래스를 부모 클래스로 하는 자식 클래스 student, salesman, housewife 클래스를 작성해주자. (person 클래스가 부모 클래스가 되어야 하므로 person 클래스를 상속해주면 된다.)

class student : public person {
    public:
        void behavior() {
            cout<<"공부하기";
        }
};

class salesman : public person {
    public:
        void behavior() {
            cout<<"판매하기";
        }
};

class housewife : public person {
    public:
        void behavior() {
            cout<<"집안일 하기";
        }
};

이제 main 함수만 작성해주면 되는데, 지금까지 필자의 C++ 글을 모두 읽은 독자분들께 한 가지 질문을 드리겠다.

혹시 위의 코드와 문제를 통해서 뭔가 느껴지는 바가 있지 않던가?

필자가 전에 작성한 다음의 글이 떠오르지는 않았는가?

“C++ Early Binding(Static Binding) & Late Binding(Dynamic Binding)”

아직 위 글을 읽지 않은 독자분들은 먼저 위 글을 읽은 후 main 함수를 어떻게 작성하면 좋을지에 대해 생각해보기 바란다.

필자는 독자 여러분께서 이러한 과정을 모두 거쳤다고 가정하고 이어서 이에 대한 풀이를 보이도록 하겠다.

사실 person 클래스 내의 behavior 함수에 접두사(Prefix)로 virtual 키워드(Keyword)가 붙었으므로, 동적 바인딩(Dynamic Binding) 개념을 이용하여 문제 풀이를 진행해야 한다.

필자가 위 글에서 필자의 생각을 다음과 같이 언급했었는데 이는 절대적인 진리는 아니나 지금과 같이 상속 관계에 놓여있는 클래스들에 대해서는 활용해볼 수 있는 Idea이다.

Early Binding(Static Binding)의 경우에는 컴파일러가 포인터의 자료형에 집중한다면, Late Binding(Dynamic Binding)의 경우에는 컴파일러가 포인터의 자료형이 아닌 그것이 가지고 있는 값에 집중한다.

또한 C++에서 동적 바인딩(Dynamic Binding) 개념을 이용하기 위해서는 멤버 함수(Member Function)에 접두사(Prefix)로 virtual 키워드(Keyword)를 작성해주어야 한다는 것도 위 글에서 설명했었다.

그러므로 지금처럼 문제의 조건에 의해 person 클래스 내의 behavior 함수(Function)에 접두사(Prefix)로 virtual 키워드(Keyword)를 작성해주었고(C++에서 동적 바인딩 개념 이용법), 자식 클래스들이 모두 person 클래스를 상속하므로 포인터형이 person인 포인터 변수를 하나 생성한 후 사용자의 입력에 따라 서로 다른 자식 클래스들(student, salesman, housewife) 중 하나에 대한 인스턴스를 생성하여 이에 대입한 다음, behavior 함수를 호출 해주면 된다.

먼저 다음처럼 main 함수 내에 NULL값을 가지는, 포인터형이 person인 포인터 변수를 선언해주고,

int main(void) {
    person* p = NULL;
}

사용자가 프로그램에 출력된 내용을 확인한 후, 제시된 메뉴(Menu)를 선택할 수 있도록 적절한 입출력문까지 작성해주자.

int main(void) {
    person* p = NULL;

    int sel;        // 사용자의 메뉴 선택에 따른 흐름 분기를 위해 정수를 입력받아 저장하기 위한 변수

    cout<<"1. student"<<endl;
    cout<<"2. salesman"<<endl;
    cout<<"3. housewife"<<endl;
    cout<<"select: ";

    cin>>sel;       // 사용자가 출력으로 제시된 사항들을 선택(입력)할 수 있는 입력문 작성
}

프로그램에서 사용자가 메뉴를 선택했다면 그에 따르는 기능이 동작해야할 것이다.

그러므로 sel의 값에 따라 흐름을 분기시켜 그에 해당하는 기능이 수행되게끔 해보자.

필자는 전체 틀을 다음과 같이 switch문으로 구성하였다.

switch(sel) {       // 사용자로부터 입력받은 sel의 값이
    case 1:         // 1이면
        break;
    case 2:         // 2이면
        break;
    case 3:         // 3이면
        break;
    default:        // 그 외
}

이제 각각에 대해서 기능을 추가해보자.

먼저 1일 때는 student 클래스의 behavior 함수가 호출되어야 하므로 먼저 student 클래스의 인스턴스를 생성하여 다음과 같이 위에서 선언했던 포인터 변수 p에 대입해주자.

switch(sel) {
    case 1:
        p = new student();
        break;
}

그 후 behavior 함수를 호출해주자.

switch(sel) {
    case 1:
        p = new student();
        p->behavior();
        break;
}

그런데 여기서 끝내면 안된다.

new 연산자를 사용하여 동적 메모리 할당(Dynamic Memory Allocation)을 한 후 모든 기능을 수행하였다면, 마지막에는 메모리를 해제해줘야 한다.

(이에 대해서는 추후에 별도의 강좌로 다룰 예정이다.)

그러므로 다음과 같이 delete 연산자를 사용하여 메모리를 해제해주자.

switch(sel) {
    case 1:
        p = new student();
        p->behavior();
        delete p;
        break;
}

나머지 기능에 대해서도 동일한 방식으로 작성해주면 된다.

그리고 마지막 default에는 해당 메뉴(Menu)가 없다는 메시지를 출력해주자.

아래에 전체 코드를 보이면서 이번 포스팅을 마무리 짓겠다.

전체 코드

#include <iostream>

using namespace std;

class person {
    public:
        virtual void behavior() {};
};

class student : public person {
    public:
        void behavior() {
            cout<<"공부하기";
        }
};

class salesman : public person {
    public:
        void behavior() {
            cout<<"판매하기";
        }
};

class housewife : public person {
    public:
        void behavior() {
            cout<<"집안일 하기";
        }
};

int main(void) {
    person* p = NULL;

    int sel;

    cout<<"1. student"<<endl;
    cout<<"2. salesman"<<endl;
    cout<<"3. housewife"<<endl;
    cout<<"select: ";

    cin>>sel;

    switch(sel) {
        case 1:
            p = new student();
            p->behavior();
            delete p;
            break;
        case 2:
            p = new salesman();
            p->behavior();
            delete p;
            break;
        case 3:
            p = new housewife();
            p->behavior();
            delete p;
            break;
        default:
            cout<<"해당 Menu 없음";
    }   

    return 0;
}

댓글남기기