언어 자료구조 알고리즘/디딤돌 C++

[C++] 37. 하향 캐스팅(dynamic_cast)

언제나휴일 2016. 4. 25. 00:44
반응형


하향 캐스팅(dynamic_cast)

이번에는 기반 형식 포인터 변수로 참조하고 있는 형식을 프로그램 동작 시에 파생 형식으로 형 변환하는 하향 캐스팅을 알아보기로 해요.

 

다형성은 캡슐화와 상속을 보다 효과적이고 현실 세계에 근접하게 표현할 수 있게 해주는 특징입니다.

하지만 기반 클래스 형식 포인터 변수로 파생 개체를 관리하는 것은 치명적인 단점이 있습니다.

 

만약 기반 클래스 형식에서는 약속할 필요가 없는 메서드가 파생 클래스 형식에 있을 때 해당 메서드의 접근 수준을 public으로 제공해도 접근하지 못합니다. 이러한 약점을 보완하기 위해 많은 OOP언어에서는 런 타임에 파생 개체 형식으로 형 변환(캐스팅)하는 방법을 제공하고 있으며 이를 하향 캐스팅이라 합니다.

 

C++언어에서는 dynamic_cast를 통해 하향 캐스팅을 제공하고 있습니다. dynamic_cast를 사용하면 원하는 형식으로 캐스팅이 가능한지 확인할 수 있습니다. 만약 캐스팅할 수 없다면 0을 반환하고 캐스팅할 수 있다면 유효한 변환을 해 줍니다.

Pianist *pianist=0;

pianist = dynamic_cast<Pianist *>(musician);//musician이 피아니스트인지 하향 캐스팅

if(pianist)//피아니스트가 맞다면

{

    pianist->Tuning();

}

 

다음은 음악가에서 파생받은 피아니스트와 드러머를 정의하고 하향 캐스팅을 통해 피아니스트 클래스에만 있는 조율 기능을 사용하는 예제 코드입니다.


Program.cpp


//하향 캐스팅

//Program.cpp

#include <iostream>

#include <string>

using namespace std;

 

class Musician

{

    string name;

public:

    Musician(string name)

    {

        this->name = name;

    }

    string GetName()const

    {

        return name;

    }

    virtual void Play()=0;

};

 

class Pianist:public Musician

{

public:

    Pianist(string name):Musician(name)

    {

    }

    virtual void Play()

    {

        cout<<GetName()<<" 딩동댕 ♩♪♬"<<endl;

    }

    void Tuning()

    {

        cout<<"도도 레레 미미 파파"<<endl;

    }

};

 

class Drummer:public Musician

{

public:

    Drummer(string name):Musician(name)

    {

    }

    virtual void Play()

    {

        cout<<GetName()<<" 두두둥~~~"<<endl;

    }

};

 

int main()

{

    Musician *musicians[2];

    musicians[0] = new Pianist("피아노맨");

    musicians[1] = new Drummer("두둥맨");

 

    Pianist *pianist=0;

    for(int i = 0; i<2; i++)

    {

        pianist = dynamic_cast<Pianist *>(musicians[i]);//players[i]가 피아니스트인지 하향 캐스팅

        if(pianist)//피아니스트가 맞다면

        {

            pianist->Tuning();

        }

        musicians[i]->Play();

    }

 

    for(int i=0;i<2;i++)

    {

        delete musicians[i];

    }

    return 0;

}

 

실행 결과

도도 레레 미미 파파

피아노맨 딩동댕 ♩♪♬

두둥맨 두두둥~~~

 

 

하지만 일반화 관계일 때 언제나 dynamic_cast를 지원하지는 않습니다. 만약 가상 메서드를 정의한 것이 없으면 dynamic_cast를 지원하지 않아요. 따라서 dynamic_cast를 사용하려면 가상 메서드가 하나 이상 정의한 형식이어야 합니다.

다형 형식이 아닙니다.


Program.cpp


//하향 캐스팅 오류

//Program.cpp

#include <iostream>

#include <string>

using namespace std;

 

class Musician

{

    string name;

public:

    Musician(string name)

    {

        this->name = name;

    }

    string GetName()const

    {

        return name;

    }

 

    void Play()

    {

        cout<<name<<" 연주하다."<<endl;

    }

};

class Pianist:public Musician

{

public:

    Pianist(string name):Musician(name){    }   

    void Tuning()

    {

        cout<<"도도 레레 미미 파파"<<endl;

    }

};

class Drummer:public Musician

{

public:

    Drummer(string name):Musician(name){    }   

};

int main()

{

    Musician *musicians[2];

    musicians[0] = new Pianist("피아노맨");

    musicians[1] = new Drummer("두둥맨");

    Pianist *pianist=0;

    for(int i = 0; i<2; i++)

    {

        pianist = dynamic_cast<Pianist *>(musicians[i]);//가상 메서드가 없어서 컴파일 오류

        if(pianist)//피아니스트가 맞다면

        {

            pianist->Tuning();

        }

        musicians[i]->Play();

    }

    for(int i=0;i<2;i++)

    {

        delete musicians[i];

    }

    return 0;

}


반응형