Type Casting
Upcasting & Downcasting
이해를 돕기위해 아래와 같은 클래스가 있다고 하자.
#include <iostream>
class Car
{
public:
Car(std::string name) : name_(name) {}
const std::string &name() const { return name_; }
private:
std::string name_;
};
class Bus : public Car
{
public:
Bus(std::string name) : Car(name), money_(0), bus_name_("BBus") {}
void GetCharge(int charge) { money_ += charge; }
int money() { return money_; }
const std::string &name() const { return bus_name_; }
private:
int money_;
const std::string bus_name_;
};
Car는 Bus일 수 있지만, Bus는 Car일 수 없기때문에 마지막 경우는 컴파일에러가 발생한다.
Car *car = new Car("myCar");
Bus *bus = new Bus("myBus");
Car *car_bus = new Bus("car_bus");
Bus *bus_car = new Car("bus_car"); # ERROR
아래 코드에서 bus를 사용해서 멤버함수를 호출하면 Car클래스에 동일한 멤버함수가 정의되어있더라도 Bus클래스의 멤버함수가 호출된다. car를 사용해서 멤버함수를 호출하면 Car의 멤버함수가 호출된다. car_bus를 사용해서 멤버함수를 호출하면 Bus객체가 들어있음에도 Car 멤버함수가 호출된다. 그리고 car_bus를 사용해서 Bus의 멤버함수에 접근할 수 없다.
위의 것들을 이해하기 위해서는 static dispatch와 dynamic dispatch를 이해해야한다.
int main()
{
Car *car = new Car("myCar");
Bus *bus = new Bus("myBus");
Car *car_bus = new Bus("car_bus");
std::cout << car->name() << std::endl; // myCar
std::cout << bus->name() << std::endl; // BBus
std::cout << car_bus->name() << std::endl; // car_bus
car->money() // ERROR
return 1;
}
Static dispatch vs Dynamic dispatch
이 개념 별거없다.
static dispatch는 컴파일러가 어떤 함수를 호출해야하는지를 컴파일 타임에 정해놓는 것이고,
dynamic dispatch는 컴파일러가 어떤 함수를 호출해야하는지를 런타임에 결정하는 것이다.
C++는 기본적으로 static dispatch를 사용한다. 그러니 변수타입을 보고 어떤 함수를 호출할지를 정하는거라서 위와 같은 현상들이 나타나는 것이다.
static_cast
class hierarchy를 사용해서 type compatibility를 검사한다.
하지만 static_cast는 완벽하게 검사해주지는 못한다.
예를 들어, 아래와 같은 class hierarchy가 있다고 생각해보자.
Bus객체를 ConvertibleCar 객체로 변환하는 것은 static cast로 방지할 수 있지만, bus_car와 같이 Car*안에 Bus가 들어있으면 변환을 해버린다.
int main() {
Car* bus_car = new Bus("myBus");
Bus* bus = static_cast<Bus*>(bus_car); // OK: Car* -> Bus*
ConvertibleCar* conv_car = static_cast<ConvertibleCar*>(bus_car); // OK: Z4ConvertibleCar* -> ConvertibleCar*
Z4ConvertibleCar* z4_conv_car = static_cast<Z4ConvertibleCar*>(bus_car); // OK: Car* -> Z4ConvertibleCar*
ConvertibleCar* conv_bus = static_cast<ConvertibleCar*>(bus); // Not allowed: Bus* -> ConvertibleCar*
Z4ConvertibleCar* z4_conv_bus = static_cast<Z4ConvertibleCar*>(bus); // Not allows: Bus* -> Z4ConvertibleCar*
return 1;
}
dynamic_cast
RTTI(RunTime Type Information)을 사용해 type compatibility를 검사한다.
casting이 안되면 nullptr을 반환하고, 가능하면 변환된 값을 반환한다.
reinterpret_cast
비트 단위로 타입을 강제로 재해석할 때 사용한다 (메모리 구조를 그대로 두고 다른 타입으로 본다).
const_cast
객체의 const나 volatile 속성을 제거하거나 추가할 때 사용한다.
'Programming > C,C++' 카테고리의 다른 글
[C, C++] Make (1) | 2025.10.10 |
---|---|
오버라이딩을 통한 다형성의 실현(virtual 개념, 오버라이딩 개념) (0) | 2022.03.01 |
참조리턴 (0) | 2022.02.23 |
복사생성자 (0) | 2022.02.23 |
연산자 중복 (0) | 2022.02.22 |