[C++] Casting

C++/Tips / / 2021. 6. 15. 11:38

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
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기