[C++] type casting

alirz-pixel·2022년 11월 14일
0

C, C++

목록 보기
4/6

static_cast

C 타입 캐스팅과 유사하지만,
컴파일러가 캐스팅을 확인하기 때문에 컴파일 타임에 형변화에 대한 타입 오류를 잡아줌

사용법 : static_cast<new type>(expression)

  • new type으로 void형 가능
  • 상속관계에 있는 포인터끼리는 변환이 가능함
    (but, 부모 클래스 -> 자식 클래스로의 변환은 unsafe 하게 작동할 수 있음)
    (dynamic_cast 를 통해 safe하게 변환 가능)
// c style
#include <iostream>

int main() {
	char a = 'a';
	int* p = (int*)&a;
	*p = 5; // runtime error

	return 0;
}
// cpp static_cast
#include <iostream>

int main() {
	char a = 'a';
	int* p = static_cast<int*>(&a); // 컴파일 에러
	*p = 5; 

	return 0;
}

타입 변환에 대한 런타임 에러를 컴파일 타임에 잡아준다

#include <iostream>

class Parent {};
class Child : public Parent {};
class NotInheritance {};

int main() {
	Parent* parent = new Parent();
	Child* child = static_cast<Child*>(parent);

	// 상속 관계에 포함되지 않으므로 컴파일 에러
	NotInheritance* notInheritance = static_cast<NotInheritance*>(parent); 

	return 0;
}

상속관계의 포인터는 문제없음



dynamic_cast

static_cast와는 반대로 캐스팅이 유효한지 런타임에 검사하도록 함
만약, 캐스팅이 유효하지 않다면 null를 반환해줌
(=bad_cast에 대한 예외처리를 따로 해줘야 함)

사용법 : dynamic_cast<new type>(expression)

부모 클래스 -> 자식 클래스로의 변환을 safe 하게 작동하게 해줌

#include <iostream>

class Parent {};
class Child : public Parent {};
class NotInheritance {
	virtual void a() {}
};

int main() {
	Child* child;
	NotInheritance* notInheritance = new NotInheritance();
	child = dynamic_cast<Child*>(notInheritance);

	if (child == nullptr) {
		std::cout << "캐스팅이 유효하지 않음" << std::endl;
	}

	return 0;
}

상속 관계에 있지 않은 형변환도 dynamic_cast에서는 동작하나 유효한 캐스팅이 아니기 때문에 null을 반환함.
NotInheritance 클래스에 virtual 함수가 추가된 이유는 C++ 에서 지원하는 RTTI 중 dynamic_cast 연산자를 사용하기 위해서이다.



reinterpret_cast

강제로 형변환을 수행함 (예를 들어 정수형을 포인터형으로 변환 가능)
다만, 강제로 하기 때문에 예상치못한 런타임 에러가 발생할 순 있음

사용법 : reinterpret<new type>(expression)

  • const의 형변환은 수행할 수 없음.
#include <iostream>

class Parent {
public:
	int a;
	Parent() {
		this->a = 2;
	}
};
class Child : public Parent {
public:
	void A() {
		std::cout << "강제로 형변환 완료 후, A 함수 호출" << std::endl;
	}
};
class NotInheritance {};

int main() {
	Child* child;
	NotInheritance* notInheritance = new NotInheritance();
	child = reinterpret_cast<Child*>(notInheritance);

	child->A(); // 형변환을 수행한 child의 A 함수는 호출이 가능함
	std::cout << child->a; // 하지만 강제로 형변환을 했기 때문에 parent의 생성자가 호출되지 않음

	return 0;
}


const_cast

포인터에 const 속성을 부여하거나 제거할 때 사용

사용법 : const_cast<new type>(expression)

#include <iostream>

int main() {
	int value = 0;

	const int* a = &value;
	int* b = const_cast<int*>(a);

	// 원래는 const int* -> int*의 변환은 컴파일 에러를 초래하지만 const_cast는 변환 가능
	*b = 15;
	std::cout << *a << std::endl;
	std::cout << *b << std::endl; 
}

0개의 댓글