티스토리 뷰
개요
C++타입의 형변환에 대해 알아보자
static cast
C 타입 캐스팅과 거의 모든면에서 동일하다. 컴파일 타임에 형변환을 감지하고 불가능하다고 판단되면 컴파일 에러를 발생시킨다. 따라서 클래스의 선언이 아래와 같을 때 주석으로 나눈 두 코드는 같은 동작을 한다.
int main() {
//~ Begin C Type casting
char CTypeChar = 'a';
int CTypeInt = CTypeChar;
//~ End C Type casting
//~ Begin C++ Type casting
char CppTypeChar = 'a';
int CppTypeInt = static_cast<int>(CppTypeChar);
//~ End C++ Type casting
return 0;
}
다만 C 타입 캐스팅과 다른점은 상속관계에 있는 클래스의 포인터형 변환을 허용한다는 점이다. 따라서 클래스 구조가 아래와 같을 때 main함수의 두 코드가 컴파일시점에 에러를 발생하는 경우가 다르다.
class Parent {
public:
virtual ~Parent();
virtual void Print();
};
Parent::~Parent() {}
void Parent::Print() { std::cout << "I’m Parent" << std::endl; }
class Driven : public Parent {
public:
void Print() override;
};
void Driven::Print() { std::cout << "I’m Driven" << std::endl; }
class Unknown {
public:
virtual ~Unknown();
void Print();
};
Unknown::~Unknown() {}
void Unknown::Print() { std::cout << "Unknown class" << std::endl; }
int main() {
//~ Begin C Type casting
Parent* CTypePerent = new Driven();
Driven* CTypeDriven = CTypeParent; // compile error
Unknown* CTypeUnknown = new Unknown();
CTypeDriven = CTypeUnknown; // compile error
//~ End C-Type casting
//~ Begin C++ Type casting
Parent* CppTypeParent = new Driven();
Driven* CppTypeDriven = static_cast<Driven*>(CppTypeParent);
Unknown* CppTypeUnknown = new Unknown();
CppTypeDriven = static_cast<Driven*>(CppTypeUnknown); // compile error
//~ End C++ Type casting
return 0;
}
dynamic cast
캐스팅이 유효한지 컴파일 타임에 검사하지 않고 런타임에 검사하도록 하는 문법. 실행도중 캐스팅이 유효한지 검사하며 불가능할 경우 NULL을 반환하여 프로그래머가 처리할 수 있도록 한다.
클래스 구조가 위와 동일하다고 할 때 아래 코드는 컴파일은 되지만 캐스팅에 실패하여 “cast fail”을 출력한다.
int main() {
Driven* CppTypeDriven;
Unknown* CppTypeUnknown = new Unknown();
CppTypeDriven = dynamic_cast<Driven*>(CppTypeUnknown);
if(CppTypeDriven != nullptr) {
CppTypeDriven->Print();
}
else {
std::cout << "cast fail" << std::endl;
}
return 0;
}
dynamic_cast를 사용하면 상속관계에 있는 클래스의 포인터끼리 형변환이 가능하지만 불가능한 경우에는 NULL을 반환한다.
int main() {
Parent* ParentHasParent = new Parent();
Parent* ParnetHasDriven = new Driven();
//~ Begin dynamic cast fail
Driven* CastedPointer = dynamic_cast<Driven*>(ParentHasParent);
if(CastedPointer){
std::cout << "cast success" << std::endl;
}
else {
std::cout << "cast fail" << std::endl;
}
//~ End dynamic cast fail
//~ Begin dynamic cast success
CastedPointer = dynamic_cast<Driven*>(ParnetHasDriven);
if(CastedPointer){
std::cout << "cast success" << std::endl;
}
else {
std::cout << "cast fail" << std::endl;
}
//~ End dynamic cast success
return 0;
}
reinterpret cast
강제로 형변환을 수행한다. 정수형을 포인터형으로, 전혀다른 클래스의 포인터로 변환할 수 있지만 논리적으로 불가능한경우 런타임에 에러가 발생할 수 있기 때문에 조심해서 사용해야한다. const의 형변환은 수행할 수 없다.
강제로 형 변환을 수행하기때문에 아래 코드는 컴파일이 된다.
int main() {
Parent* p = new Parent();
Unknown* u = reinterpret_cast<Unknown*>(p);
return 0;
}
const cast
포인터에 const 속성을 부여하거나 제거할 때 사용한다. 아래처럼 상수성을 제거하여 사용할 수 있다.
int main() {
int value = 10;
int value2 = 20;
const int* a = &value;
int* b = const_cast<int*>(a);
*b = 15;
std::cout << *b << std::endl;
}
마치며
C++코드를 짜면서 대충 쓰고있긴 했지만 이번기회에 정확히 짚고넘어가자는 생각으로 포스팅을 쓰기시작했다. 그런데 공부를 하고나서도 static_cast랑 dynamic_cast 말고는 딱히 어디에 써야할지 감이 안잡힌다.
'Programming > C++' 카테고리의 다른 글
C++ Expert | 상황별 const의 의미 (0) | 2020.09.06 |
---|---|
C++ - 스마트 포인터(smart pointer) (2) | 2019.03.29 |
C++ - 클래스 관계 용어 정리 (0) | 2018.03.02 |
C++ - 메모리 해제 (0) | 2017.12.30 |
C++ - 메모리 생성 (0) | 2017.12.30 |
- Total
- Today
- Yesterday
- mongoDB
- game
- winsock
- 수학
- JSP
- C++
- ios
- 운영체제
- rxswift
- 데이터베이스
- C/C++
- 국내여행
- Git
- SHADER
- swift
- Spring
- SwiftUI
- OS
- ue4
- 자료구조
- Cocos2d-x
- C
- database
- DesignPattern
- SOCKET
- Java
- machine learing
- 알고리즘
- 드라마
- scala
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |