본문 바로가기

프로그래밍/C++

업캐스팅 &&다운캐스팅

https://rehtorb-algorithm.tistory.com/8

참조한 사이트

 

 

c++에서 자주 쓰이고 아주 유용한 두가지 캐스팅에 대해서 공부해보자.

 

업캐스팅

 

우선 업캐스팅이란 부모클래스의 자식클래스의 객체를 부모클래스의 포인터로 가리킬때 일어난다.

업캐스팅을 통해 자식클래스를 부모클래스의 객체처럼 다룰 수 있게 해주어야할 때 사용한다.

즉 코드의 재 사용성을 높이기 위해서 사용해준다고 할 수 있다.

하지만 업캐스팅을 하면 기본클래스에 정의된 멤버(함수)만 호출할 수 있기 떄문에 파생클래스의 고유 함수는 사용할 수 가 없게 된다.

이때 다시 다운캐스팅의 과정을 통해 본래 함수를 사용하게 해주어야한다.

 Parents* parents = new Child;

또한 업캐스팅의 경우에는 명시적인 형변환이 필요하지 않지만

다운캐스팅의 경우에는 명시적인 형변환이 필요하다.

글로는 이해가 되지않으니 예시를 통해 알아보자

 

더보기
class CBase 
{
    public: virtual void Show() 
    { 
    	std::cout << "CBase" << std::endl; 
    } 
}; 

class CDerived1 : public CBase 
{ 
    public: virtual void Show() 
    { 
    	std::cout << "CDerived1" << std::endl; 
    } //overriding 
}; 
    

class CDerived2 : public CBase
{ 
    public: virtual void Show() 
    {
    	std::cout << "CDerived2" << std::endl; 
    } //overriding 
};

 

이러한 코드가 있다고 하였을때

이러한 결과값이 나오기 위해서는 3가지 경우의 수가 있는데

가장 간단하게는

더보기

1번째방법

main int main(void) 
{
    CBase base; 
    CDerived1 derived1; 
    CDerived2 derived2; 
    
    base.Show(); 
    derived1.Show();
    derived2.Show(); 
    
    return 0; 
}

 

포인터와 동적바인딩을 활용한 방법으로는

더보기
main int main(void) 
{ 
    CBase* pInterface = nullptr; 
    CBase* pBase = new CBase; 
    CDerived1* pDerived1 = new CDerived1; 
    CDerived2* pDerived2 = new CDerived2; 
    
    pInterface = pBase; 
    pInterface->Show(); 
    
    pInterface = pDerived1; 
    pInterface->Show(); 
    
    pInterface = pDerived2; 
    pInterface->Show(); 
    
    delete pBase; 
    delete pDerived1; 
    delete pDerived2; 
    return 0; 
}

세번째 map을 활용한 방법으로는

더보기
main int main(void) 
{ 
    std::string classNames[3] = {"CBase", "CDerived1", "CDerived2" }; 
    std::string className = ""; 
    std::map<std::string, CBase*> mapData; 
    
    CBase* pInterface = nullptr; 
    CBase* pBase = new CBase; 
    CDerived1* pDerived1 = new CDerived1; 
    CDerived2* pDerived2 = new CDerived2; 
    
    mapData.insert(std::make_pair(classNames[0], pBase));
    mapData.insert(std::make_pair(classNames[1], pDerived1));
    mapData.insert(std::make_pair(classNames[2], pDerived2)); 
    
    for (int idx = 0; idx < 3; idx++) 
    { 
		className = classNames[idx]; 
        pInterface = mapData.find(className)->second; //업 캐스팅 pInterface->Show(); 
    } 
    
    mapData.clear(); 
    
    delete pBase; 
    delete pDerived1; 
    delete pDerived2; 
    
    return 0;
}

 

다운캐스팅은 이미 업캐스팅이 진행된 상황에서 본래자신의 기능을 사용하기 위해서 사용되는데

동일한 타입의 포인터가 동일한 타입을 가리키게끔 유도하는것이다

형변환시에는 반드시 명시적 형변환을 해줘야한다.

더보기
class CBase 
{
    public: virtual void Show() 
    { 
		std::cout << "CBase" << std::endl; 
    } 
    
    void A() 
    { 
    	std::cout << "A의 고유 기능" << std::endl; 
    }
}; 


class CDerived1 : public CBase 
{ 
	public: virtual void Show() 
    { 
    	std::cout << "CDerived1" << std::endl; 
    } 
    
    void B() 
    { 
    	std::cout << "B의 고유 기능" << std::endl; 
    } 
}; 


class CDerived2 : public CBase 
{ 
	public: virtual void Show() 
    { 
    	std::cout << "CDerived2" << std::endl; 
    } 
    
    void C() 
    { 
    	std::cout << "C의 고유 기능" << std::endl; 
    } 
};
int main(void) 
{
    std::string classNames[3] = { "CBase", "CDerived1", "CDerived2" }; 
    std::string className = ""; 
    std::map<std::string, CBase*> mapData; 
    
    CBase* pInterface = nullptr; 
    CBase* pBase = new CBase; 
    CDerived1* pDerived1 = new CDerived1; 
    CDerived2* pDerived2 = new CDerived2; 
    
    mapData.insert(std::make_pair(classNames[0], pBase)); 
    mapData.insert(std::make_pair(classNames[1], pDerived1)); 
    mapData.insert(std::make_pair(classNames[2], pDerived2)); 
    
    for (int idx = 0; idx < 3; idx++) 
    { 
    	className = classNames[idx]; 
        pInterface = mapData.find(className)->second; //업 캐스팅 
        
        switch (idx) 
        { 
        case 0: 
            pBase = (CBase*)pInterface; //다운 캐스팅(pInterface를 CBase로 타입 캐스팅) 
            pBase->A(); 
            break; 
        case 1: 
            pDerived1 = (CDerived1*)pInterface; //다운 캐스팅 
            pDerived1->B(); 
            break; 
        case 2: 
            pDerived2 = (CDerived2*)pInterface; //다운 캐스팅 
            pDerived2->C(); 
            break; 
        default: 
            break; 
        } 
    } 
    
    mapData.clear(); 
    
    delete pBase; 
    delete pDerived1; 
    delete pDerived2; 
    
    return 0; 
}

 

'프로그래밍 > C++' 카테고리의 다른 글

Push_back && emplace_back  (0) 2024.02.29
객체지향(C++)과 절차지향(C)의 차이  (0) 2024.02.29
NameSpace  (1) 2024.02.29
C++ 기본 입출  (0) 2024.02.13
프로그래밍을 위한 기초지식  (0) 2024.02.13