캐스팅이란?
- 기존의 C언어에서는 (자료형)변수 방식으로 간단하게 형변환을 하였는데 이것을 보완하여 C++에 추가한 방식이 바로 캐스팅(Casting)입니다. 캐스팅에는 총 4가지가 있습니다.
1. static_cast<Type>
static_cast는 변수의 자료형을 안전하게 변환하여 줍니다. 실수<->정수 변환 과 문자<->정수, 문자<->실수도 변환 가능합니다.
double num = 100.9;
cout << static_cast<int>(num) << endl;
실수형에서 정수형으로 변환시 소수점을 전부 버리고 변환됩니다.
char num = 'a';
cout << static_cast<int>(num) << endl;
문자형에서 정수형으로 변환시에는 아스키코드(ASCII CODE)값을 반환하여 줍니다.
double num = 72.6;
cout << static_cast<char>(num) << endl;
실수형에서 문자형으로 변환시에는 실수를 정수값으로 변환후 그값에 맞는 아스키코드(ASCII CODE)를 반환하여 줍니다.
2. dynamic_cast<Type>
- dynamic_cast는 보다 안전한 업캐스팅과 다운캐스팅을 제공하여 주고, 상속 관계가 아닐경우 형변환이 불가능하다고 알려줍니다.
#include <iostream>
using namespace std;
class Parent {};
class Friend {};
int main()
{
Friend* myFriend = new Friend();
Parent* parent;
parent = dynamic_cast<Parent*>(myFriend); // Error
return 0;
}
이런식으로 독립적인 다른 클래스로 포인터형 변환을 시도할시에는 컴파일단계에서 오류를 출력하여 줍니다.
3. const_cast<Type>
const_cast는 const 변수의 값을 바꾸고 싶을때 사용됩니다. 허나, const변수의 값을 직접적으로 바꿀 수는 없고 const 변수를 가르키는 const 포인터의 주소값을 일반 포인터로 전달 후 접근 하여 변환하여 줍니다.
#include <iostream>
using namespace std;
int main()
{
const int cNum = 100;
const int* cPtr = &cNum;
int* nPtr = nullptr;
nPtr = const_cast<int*>(cPtr);
cout << "cNum : " << cNum << endl;
cout << "cPtr : " << (*cPtr) << endl;
cout << "nPtr : " << (*nPtr) << endl;
return 0;
}
이렇게 const_cast를 사용하면 일반 포인터로도 const변수의 주소값을 가르킬 수 있습니다.
#include <iostream>
using namespace std;
int main()
{
const int cNum = 100;
const int* cPtr = &cNum;
int* nPtr = nullptr;
nPtr = const_cast<int*>(cPtr);
(*nPtr) = 200;
cout << "cNum : " << cNum << endl;
cout << "cPtr : " << (*cPtr) << endl;
cout << "nPtr : " << (*nPtr) << endl;
return 0;
}
이런 방식으로 const변수의 값을 직접 바꾸지는 못하지만 const 포인터가 가르키는 변수값은 바꿀 수 있습니다.
4. reinterpret_cast<Type>
reinterpret_cast는 cast중에서도 가장 강한 강제성을 가집니다. 정수->포인터 변환 혹은 서로 상속관계가 아닌 클래스의 캐스팅 처럼 일반적이지 않은 캐스팅을 가능하게 해줍니다. 허나, 컴파일에서는 문제 없이 넘어가더라도 런타임 때 오류가 없다고 보장을 해주진 않기 때문에 사용에 주의가 필요합니다.
#include <iostream>
using namespace std;
int main()
{
int num = 100;
int* ptr = #
cout << "num : " << num << endl;
cout << "ptr : " << ptr << endl;
return 0;
}
#include <iostream>
using namespace std;
class ClassA {
public:
void print() { cout << "ClassA" << endl; }
};
class ClassB {
public:
void print() { cout << "ClassB" << endl; }
};
int main()
{
ClassA* classA = new ClassA();
ClassB* classB;
classB = reinterpret_cast<ClassB*>(classA);
classB->print();
return 0;
}
이렇게 reinterpret을 사용하면 전혀 다른 두 클래스의 캐스팅이 가능해집니다.
'C++' 카테고리의 다른 글
[C++] 스마트 포인터의 사용법 (0) | 2022.12.14 |
---|---|
[C++] inline 함수의 장단점 (0) | 2022.12.12 |
[C++] 참조 변수 사용법 (0) | 2022.12.09 |
[C++] 추상 클래스(Abstract Class)와 인터페이스(Interface)의 차이점 (0) | 2022.10.07 |
[C++] 일반 함수와 가상 함수의 차이점 & 가상 소멸자 사용 이유 (1) | 2022.10.06 |