본문 바로가기
C++

[C++] 캐스팅(Casting) 하는법

728x90
반응형

캐스팅이란?

    - 기존의 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 = &num;

	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을 사용하면 전혀 다른 두 클래스의 캐스팅이 가능해집니다.

반응형