728x90
반응형
[ 업캐스팅 ]
int main()
{
Base p;
Derived c;
std::cout << "=== 포인터 ===" << std::endl;
Base* p_c = &c;
p_c->what();
return 0;
}
실행 결과
위 코드 중 7행은 Derived의 객체 c를 Base 객체를 가리키는 포인터에 넣은 것을 의미한다.
Base* p_c = &c;
Derived 객체 c는 Base를 상속받아 만들어졌기 때문에 Base 객체를 가리키는 포인터가 c를 가리켜도 무방하다.
하지만, p_c는 Derived 객체의 Base에 해당하는 부분에 대한 정보밖에 없다.
p_c는 엄연히 Base 객체를 가리키는 포인터이므로, p의 what()을 실행한다면 Base의 what() 함수를 실행하게 된다.
이러한 형태의 캐스팅(파생 클래스에서 기반 클래스로 캐스팅하는 것)을 업 캐스팅이라고 한다.
728x90
[ 다운캐스팅 ]
#include <iostream>
#include <string>
class Base
{
std::string s;
public:
Base() : s("기반") { std::cout << "기반 클래스" << std::endl; }
void what() { std::cout << s << std::endl; }
};
class Derived : public Base
{
std::string s;
public:
Derived() : s("파생"), Base() { std::cout << "파생 클래스" << std::endl; }
void what() { std::cout << s << std::endl; }
};
int main()
{
Base p;
Derived c;
std::cout << "=== 포인터 버전 ===" << std::endl;
Derived *p_p = &p;
p_p->what();
return 0;
}
위 코드를 컴파일해 보면 24행에서 다음과 같은 오류가 발생한다.
Derived* 포인터가 만약 Base 클래스의 객체를 가리킨다고 가정해 보자.
25행에서 p_p->what()을 하게 되면 p_p는 Derived*를 가리키는 포인터이므로 Derived*의 what() 함수가 호출이 되어야 한다.
하지만 p_p가 가리키는 객체는 Base라서 Derived에 대한 정보가 없으므로 호출하지 못하여 이 행은 실행이 불가능하다.
✓ 업캐스팅 (upcasting)
- 파생 클래스를 기반 클래스에 할당한다.
- 파생 클래스는 구체화된 객체를 추상적인 객체에 할당하니 별로 문제가 되지 않는다.
- 오히려 파생 클래스들의 다형성을 보편화시켜 다룰 수 있는 장점이 있다.
✓ 다운캐스팅 (downcasting)
- 기반 클래스를 파생 클래스에 할당한다.
- 기반 클래스에 없고 파생 클래스에 존재하는 멤버들에게 접근하려고 할 때 에러 발생의 위험이 있다.
- 이러한 위험을 컴파일 시 차단하기 위해 dynamic_cast가 생겨났다.
728x90
반응형