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 |