1. Casting
=> 캐스팅은 A라는 자료형에서 B라는 자료형으로 형변환을 하는 것을 말함
=> 변환에는 두가지가 존재함
-> Implicit Conversion
-> Explicit Conversion
2. Implicit Conversion
=> 암시적 변환이라 하며, 프로그래머의 개입 없이 Compiler에 의해 자동으로 수행되는 변환
=> 한 기본 자료형이 예상되나, 다른 기본 자료형이 제공될 때 마다 수행
=> 승격과 변환이 존재함
-> 승격 : 더 큰 유사한 자료형으로 변경[Data 손실 발생 X]
long num(64); // int -> long
double dnum(0.12f); // float -> double
-> 변환 : 더 작은 유사한 자료형으로 변환하거나, 다른 자료형으로 변환하는 것[Data 손실이 발생할 수 있음]
int var = 10;
float fvar = var;
=> 변환을 할 때에, 피연산자의 우선순위를 따지고 해야함
-> 피연산자의 자료형이 int보다 작은 정수(short 등)이면 int / unsigned int로 승격
-> 자료형이 같지 않으면, 컴파일러는 가장 높은 우선순위 피연산자를찾고 다른 피연산자를 일치시킴
-> 피연산자 우선순위
1. long double [highest]
2. double
3. float
4. unsigned long long
5. long long
6. unsigned long
7. unsigned int
8. int [lowest]
3. Explicit conversion
=> 명시적 변환이라 하며, 프로그래머가 명시적으로 변환을 지정한 경우에만 수행
int var = 10;
float fvar = (float) var / 10;
=> Explicit conversion의 경우 네가지의 casting operator가 존재
-> static_cast : static_cast를 사용한 형변환[static_cast<Type>(var)]
-> compile time에 type을 검사하는 장점이 존재
-> byte가 다르거나, data 손실이 발생할 수 있는 경우에 명시적으로 사용하기도 함
-> 관련된 포인터 유형간에 변환할 수 도 있음
char var = 'a';
cout << static_cast<int>(var) << endl; // 97
-> const_cast : 상수성을 제거하기 위한 형변환[const_cast<Type>(var)]
-> 변수 포인터(*) 또는 참조형의 상수성(const) 그리고 volatile을 잠깐 제거하는데 사용
-> 이외의 형변환에는 불가능(함수 포인터도 불가능)
-> 다만 Const가 기본적으로 변경하지 않기 위해 사용하는 것이기에, 사용하지 않는것이 제일 좋음
// 1. pointer const
int a = 10;
const int* var = &a;
cout << a << endl; // 10
int* newvar = const_cast<int*>(var);
*newvar = 11;
cout << a << endl; // 11
// 2. reference const
int a = 10;
const int& var = a;
cout << a << endl; // 10
int& newvar = const_cast<int&>(var);
newvar = 11;
cout << a << endl; // 11
-> reinterpret_cast : 포인터 타입끼리의 변환[reinterpret_cast<Type>(var)]
-> 포인터 및 변수간의 변환이 가능(포인터 -> 변수 / 변수->포인터 / 포인터->포인터)
-> 이외의 형변환에는 불가능(자료형간의 변환도 불가능)
-> 포인터간의 변환의 경우 결과 값이 잘못 사용되면 예상치 못한 값이 출력될 수 있음(100번 주소라던가...)
-> 보통은 패킷 통신시 자료를 포인터로 받아올때 사용
// 1. 변수 -> 변수포인터* (int -> int*)
int a = 159753123;
int *aptr;
aptr = reinterpret_cast<int*>(a);
cout << *aptr << endl;
//2. 변수포인터 -> 변수포인터( int* -> char*)
int *aptr2 = &a;
char * acptr;
acptr = reinterpret_cast<char*>(aptr2);
cout << *acptr << endl;
-> dynamic_cast : 부모클래스의 포인터에서 자식 클래스의 포인터로 다운캐스팅[dynamic_cast<Type>var]
-> Runtime에 Downcasting 여부를 검사하여, runtime cost가 높음
class Par
{
public:
virtual void printA() {} // C2683 : Par이 다형성을 갖추어야만 dynamic_cast가 성립됨
void print()
{
cout << "Parent class" << endl;
}
};
class Chil : public Par
{
public:
void print()
{
cout << "Children class" << endl;
}
};
int main()
{
Par* pPar = new Chil();
Chil* pChil = dynamic_cast<Chil*>(pPar);
if (pChil == nullptr)
cout << "Runtime Error" << endl;
else
pChil->print();
delete pPar;
return 0;
}
/*
출력값 : Children class
*/
-> C-style cast : C에서부터 기본적으로 사용되던 cast[Type(var)]
-> compile time에 검사되지 않는 단점이 존재
int num1 = 10;
int num2 = 4;
float fnum = float(num1) / num2;
'C++ > Tips' 카테고리의 다른 글
[C++] Union (0) | 2021.06.18 |
---|---|
[c++] inline (0) | 2021.06.16 |
[C++] initialization (0) | 2021.06.14 |
[c++ 14] deprecated (0) | 2021.06.11 |
[c++ 11]Range based for (0) | 2021.06.10 |