<aside> <img src="/icons/list_gray.svg" alt="/icons/list_gray.svg" width="40px" />
목차
</aside>
타입 변환? 갑자기 타입 변환을 살펴봐야 할까 싶다. 그러나, 우리 앞서 살펴봤듯이, 포인터는 동적 할당에서 메모리 주소를 다루는 핵심 도구인데, 이 포인터를 제대로 활용하려면 타입 변환을 이해하는 것이 필수적이다.
예를 들어서, 위 코드에서 살펴봤듯이 void* 포인터를 특정 타입의 포인터로 바꾸거나, 상속 관계에 있는 클래스들의 포인터를 서로 변환해야 할 때가 많다. 이런 변환 과정에서 문제가 생기지 않도록 타입 변환의 개념과 규칙을 잘 알아두어야 한다.
그리고 메모리를 관리할 때 타입 변환은 데이터를 다르게 해석하거나 재사용하는 데 매우 중요한 역할을 한다. 따라서 동적 할당과 타입 변환은 서로 뗄 수 없는 관계라고 할 수 있다.
크게 두 가지 타입의 변환이 존재한다.
값 타입 변환
참조 타입 변환
참조 타입 변환
int main()
{
int a = 123456789;
float b = (float&)a;
cout << b << endl;
}

위 코드를 실행하면 123456789라는 정수가 float 타입으로 재해석되어 출력된다. 이때 실제 메모리의 비트 패턴은 변경되지 않고, 단지 float의 관점에서 해석되기 때문에 전혀 다른 값이 출력된다.
위는 참조 타입 변환이 메모리의 실제 내용은 그대로 두고 단순히 해석 방식만 바꾼다는 것을 보여주는 좋은 예시이기도 하다.
타입 변환은 안전도에 따라 분류할 수도 있다. 안전도는 데이터의 의미와 값이 변환 과정에서 얼마나 보존되는지를 나타내는 중요한 지표이다.
안전한 변환 (Safe Conversion)
int -> longfloat -> doubleDog -> Animal, 모든 Dog는 Animal이므로 안전불안전한 변환 (Unsafe Conversion)
double -> int (소수점 손실)long -> short (상위 비트 손실)타입 변환은 프로그래머의 의도성에 따라서도 분류할 수 있다. 의도성 분류는 타입 변환이 코드에서 얼마나 명시적으로 드러나는지를 기준으로 한다.
암시적 변환 (Implicit Conversion)
int를 float에 대입할 때 자동으로 float로 변환short → int)명시적 변환 (Explicit Conversion)
(type)valuestatic_cast, dynamic_cast 등값 변환
class Knight
{
public:
int _hp = 10;
};
class Dog
{
public:
int _age = 20;
int _cuteness = 2;
};
int main()
{
Knight k;
**Dog d = (Dog)k;**
}
생성자 선언
**Dog(const Knight &knight)
{
_age = knight._hp;
}**
Knight 타입을 매개변수로 받는 생성자를 Dog 클래스에 추가하여, Knight 객체의 _hp 값을 Dog 객체의 _age에 복사하는 형태로 변환을 구현했다.연산자 오버로딩
**operator Knight()
{
return (Knight)(*this);
}**
**Knight knight2 = d;**
Dog 클래스에 Knight 타입으로의 변환 연산자를 추가하여, Dog 객체를 Knight 타입으로 자동 변환할 수 있게 만들었다.참조 타입 변환
**Dog& d = (Dog&)k;**
어셈블리 레벨에서 보면 포인터와 참조는 동일한 방식으로 메모리를 다룬다.