Q) 묵시적 형 변환, 명시적 형 변환은 무엇인가요?
int i = 65;
char ch1 = 65; // print : A
char ch1 = i; // 묵시적 형 변환(Implicit Cast)
char ch2 = (char)i; // 암시적 형 변환(Explicit Cast)
우선 형 변환은 변수의 타입(Type)을 다른 타입으로 바꾸는 행위입니다. // 타입 캐스팅
묵시적 형 변환 = 타입을 언급없이
암시적 형 변환 = 타입을 언급을 하여
형 변환을 합니다.
이때 형 변환시 타입 체크를 하지 않아서 버그를 만들기가 쉽습니다.
따라서 c++에서의 타입 캐스팅은 일종의 안정 장치를 걸 수 있는데요.
Q) 타입캐스팅 안정성을 위한 장치는 어떤게 있을까요?
A) static_cast, const_cast, dynamic_cast, reinterpret_cast
static_cast
#include <iostream>
using namespace std;
int main() {
double pi = 3.14;
// double pointer -> int pointer 무모한 행위
// but allowed
int* ptr = (int*)π
cout << *ptr << endl;
// static_cast, not allowed
int* qtr = static_cast<int*>(&pi);
}
- 이성적인 변환만 허용합니다.
- 컴파일 타임에 동작합니다.
reinterpret_cast
#include <iostream>
using namespace std;
int main() {
double pi = 3.14;
int* ptr = reinterpret_cast<int*>(&pi);
cout << *ptr << endl;
int* ptr = reinterpret_cast<int*>(0xAABBCCDD);
cout << *ptr << endl;
}
- 메모리 공간 재해석
- 연관성이 없는 포인터 타입의 형 변환이 가능 (static_cast와 차이점)
const_cast
#include <iostream>
using namespace std;
int main()
{
char str[] = "Hello";
const char* ptr = str;
// ptr = str[0] ** error ** : ptr이 상수이기 떄문에
char* c = const_cast<char*>(ptr);
c[1] = 'A';
cout << c << endl;
// print : HAllo; -> 상수 포인터인 값에도 접근을 해버릴 수 있다.
}
- 객체의 상수성 제거
- 주로 포인터 타입, 참조형에 대해서 const속성을 잠깐 제거할 때 사용
dynamic_cast
dynamic_cast를 알기 전에 포스팅을 통해 DownCasting, RTTI에 대해 알고가면 이해하기 쉬울거에요.
#include <iostream>
using namespace std;
class Animal {
public:
virtual ~Animal() {}
void cry() { cout << "Crrr" << endl; }
};
class Dog : public Animal {
public:
int color;
void cry() { cout << "Mung" << endl; }
};
void foo(Animal* p) {
Dog* pDog = dynamic_cast<Dog*>(p);
if (pDog != 0) pDog->cry();
else p->cry();
}
int main()
{
Animal a;
Dog d;
foo(&a);
foo(&d);
}
dynamic_cast 연산자는 RTTI의 요소 중 하나입니다.
- 주로 Downcasting ( 부모 클래스 -> 자식 클래스 포인터로 다운캐스팅)
- 런타임 시간에 다운 캐스팅이 가능한지 능동적 판단을 합니다.
- 형변환 실패시 Null ptr 혹은 Exception return