[디딤돌 C++] 33. 메서드의 다형성

형식의 다형성은 기반 형식 포인터 변수로 파생 형식 개체를 설정하거나 기반 형식 참조 변수로 파생 형식 개체를 설정할 수 있는 특징이죠. 그런데 형식의 다형성만 제공한다면 기반 형식 변수로 멤버 메서드를 호출하면 실제 개체 형식에 관계없이 기반 형식에 정의한 메서드가 동작합니다.

메서드의 다형성은 기반 형식 변수로 멤버 메서드를 호출하였을 때 실제 개체 형식에 정의한 메서드가 동작할 수 있는 OOP언어의 특징입니다.

일반화 관계 클래스 다이어그램

예를 들어 음악가 형식을 기반으로 파생한 형식으로 피아니스트와 드러머가 있다고 가정할게요. 그리고 음악가에는 “연주하다.”와 “인사하다.” 기능을 제공할거예요.

“인사하다.” 기능은 파생 형식에 관계없이 같은 동작을 수행하지만 “연주하다.” 기능은 파생 형식에 따라 다르게 동작하게 구현하려면 어떻게 해야 할까요?

이 때는 기반 형식인 음악가 클래스에서 “연주하다.” 기능을 선언할 때 여기서 기능을 정의하는 것은 가상으로 정의하는 것이며 파생 형식에서 다르게 재정의할 수 있다는 의미로 virtual 키워드를 명시합니다.

class Musician
{
    string name;
public:
    Musician(string name)
    {
        this->name = name;
    }
    virtual void Play()
    {
        cout<<name<<" 연주하다."<<endl;
    }
    void Introduce()
    {
        cout<<name<<" 음악가: 안녕"<<endl;
    }    
    string GetName()const
    {
        return name;
    }
};

이처럼 virtual 키워드를 사용하여 메서드를 선언하면 파생 형식에서 이를 재정의(override)하였을 때 기반 형식 포인터 변수로 메서드를 호출하면 실제 개체 형식의 메서드를 수행합니다.

다음의 예제 코드는 기반 형식인 음악가 클래스에서 “연주하다.“ 기능은 가상 메서드로 정의하고 파생 형식인 피아니스트와 드러머 클래스에서 재정의(override)한 것입니다. 프로그램을 실행시켜 보면 음악가 형식 포인터 변수에 피아니스트 개체를 전달하면 “연주하다.” 기능은 실제 개체 형식인 피아니스트 클래스에 정의한 메서드를 수행하는 것을 확인할 수 있습니다.

//메서드의 다형성
//Program.cpp
#include <iostream>
#include <string>
using namespace std;
class Musician
{
    string name;
public:
    Musician(string name)
    {
        this->name = name;
    }
    virtual void Play()
    {
        cout<<name<<" 연주하다."<<endl;
    }
    void Introduce()
    {
        cout<<name<<" 음악가: 안녕"<<endl;
    }    
    string GetName()const
    {
        return name;
    }
};

class Pianist:public Musician
{
public:
    Pianist(string name):Musician(name)
    {
    }
    virtual void Play()
    {
        cout<<GetName()<<" 연주하다."<<endl;
        cout<<"딩동댕 ♩♪♬"<<endl;
    }
};
class Drummer:public Musician
{
public:
    Drummer(string name):Musician(name)
    {
    }
    virtual void Play()
    {
        cout<<GetName()<<" 연주하다."<<endl;
        cout<<"두두둥~~~"<<endl;
    }
};

void StartConcert(Musician *musician);
void StartConcert(Musician &musician);

int main()
{
    Pianist *pianist1 = new Pianist("피아노맨1");
    Drummer *drummer1 = new Drummer("두둥맨1");
    StartConcert(pianist1);
    StartConcert(drummer1);
    delete pianist1;
    delete drummer1;

    Pianist pianist2("피아노맨2");
    Drummer drummer2("두둥맨2");
    StartConcert(pianist2);
    StartConcert(drummer2);
    return 0;
}
void StartConcert(Musician *musician)
{
    musician->Introduce();
    musician->Play();
}
void StartConcert(Musician &musician)
{
    musician.Introduce();
    musician.Play();
}

▷ 실행 결과

피아노맨1 음악가: 안녕

피아노맨1 연주하다.

딩동댕 ♩♪♬

두둥맨1 음악가: 안녕

두둥맨1 연주하다.

두두둥~~~

피아노맨2 음악가: 안녕

피아노맨2 연주하다.

딩동댕 ♩♪♬

두둥맨2 음악가: 안녕

두둥맨2 연주하다.

두두둥~~~