[C++기초] 8. 캐스팅

INDEX

  1. C 스타일 캐스팅
  2. static_cast
  3. reinterpret_cast
  4. const_cast
  5. dynamic_cast
  6. staic_cast vs reinterpret_cast
  7. static_cast vs dynamic_cast
  8. 캐스팅 규칙
  9. 정리

C 스타일 캐스팅

암시적 캐스팅

명시적 캐스팅

C 스타일 캐스팅

정적 캐스팅

C

float number1 = 3.f;
int number2 = (int)number1;
Animal* myPet = new Cat(2, "Coco");
Cat* myCat = (Cat*)myPet;

C++

float number1 = 3.f;
int number2 = static_cast<int>(number1);
Animal* myPet = new Cat(2,"Coco");
Cat* myCat = static_cast<Cat*>(myPet);

리인터프리트(reinterpret) 캐스팅

C

Animal* myPet = new Cat(2,"Coco");
unsigned int myPetAddr = (unsigned int)myPet;
cout<<"address:"<<hex<<myPet;

C++

Animal* myPet = new Cat(2,"Coco");
unsigned int myPetAddr = reinterpret_cast<unsigned int>(myPet);
cout<<"address:"<<hex<<myPet;

컨스트(const) 캐스팅

C

void Foo(const Animal* ptr)
{
	//Bad code
	Animal* animal = (Animal*)ptr;
	animal->SetAge(5);
}

C++

void Foo(const Animal* ptr)
{
	//Bad code
	Animal* animal = const_cast<Animal*>ptr;
	animal->SetAge(5);
}

동적(dynamic) 캐스팅

C

Cat* myCat = (Cat*)myPet;

C++

Cat* myCat = dynamic_cast<Cat*>(myPet);

static_cast

정적 캐스팅

C의 경우

//1.값
int number2 = (int)number1;

//2.개채포인터
Cat* myCat = (Cat*)myPet;

C++의 경우

//1.값
int number2 = static_cast<int>(number1);

//2.개채포인터
Cat* myCat = static_cast<Cat*>(myPet);
    • 두 숫자 형 간의 변환

    • 값을 유지 (단 반올림 오차는 제외)

    • 이진수 표기는 달라질 수 있음

      예시1

      int number1 = 3;
      short number2 = static_cast<short>(number1);
      

      static_cast 1

      비트값과 값 둘 다 바뀌지 않음

      예시2

      int number1 = 3;
      short number2 = static_cast<short>(number1);
      

      static_cast 2

      비트값은 달라지지만, 사람이 느끼는 값은 달리지지 않음

    2.개체 포인터

    • 변수형 체크 후 베이스 클래스를 파생 클래스로 변환

    • 컴파일 시에만 형 체크 가능

    • 실행 도중 여전히 크래시가 날 수 있음

      예시1

      Ainmal* myPet = new Cat(2, "Coco");
      Cat* myCat = static_cast<Cat*>(myPet); //OK
      Dog* myDog = static_cast<Dog*>(myPet); //컴파일은 됨. 그러나 위험(크래시가 날 수 있다)
      myDog->GetDogHouseName();
      

      예시2

      Animal* myPet = new Cat(2, "Coco");
      
      House* myHouse = static_cast<House*>(myPet); // 컴파일 에러
      myHouse->GetAddress();
      

static_cast 사용법

static_cast<<type>> (<variable-name>)

예시

int number2 = static_cast<int>(number1);

Dog* myDog = static_cast<Dog*>(myPet);

reinterpret_cast

reinterpret_cast

reinterpret_cast 사용법

reinterpret_cast<<type>> (<variable-name>)

예시

Cat* myCat = reinterpret_cast<Cat*>(myPetAddress);

아니 얘를 어따써??

const_cast

const_cast

const_cast를 사용해야 할 때는?

dynamic_cast

dynamic_cast

C의 경우

Animal* myPet = new Cat();

//Compiles
Dog* myDog = (Dog*)myPet;

//Compiles, but crashes
myDog->GetHouseName();

C++의 경우

Animal* myPet = new Cat();

//Compiles, and returns NULL
Dog* myDog = dynamic_cast<Dog*>myPet;

//Compiles, GetHouseName() will not execute
if(myDog != NULL)
{
	myDog->GetHouseName();
}

dynamic_cast사용법

dynamic_cast <<type>> (<variable_name>)

예시

Dog* myDog = dynamic_cast<Dog*>(myPet);

staic_cast vs reinterpret_cast

예시

int* signedNumber = new int(-10);

//컴파일 에러. 유효하지 않은 형변환
unsigned int* unsignedNumber1 = static_cast<unsigned int*>(signedNumber);

//컴파일은 됨. 허나 값은 더 이상 -10이 아님
unsigned int* unsignedNumber2 = reinterpret_cast<unsigned int*>(signedNumber);

static_cast vs dynamic_cast

예시

static_cast 예시

Animal* myPet = new Cat();

//컴파일됨
Dog* myDog = static_cast<Dog*>(myPet);

//컴파일됨. 허나 실행 중 어떻게 동작할지 모름. 크래시?
myDog->GetHouseName();

dynamic_cast 예시

Animal* myPet = new Cat();

//컴파일됨. 그리고 언제나 NULL을 반환
Dog* myDog = dynamic_cast<Dog*>(myPet);

//컴파일됨. GetHouseName()은 실행되지 않음
if(myDog)
{
	mydog->GetHouseName();
}

캐스팅 규칙

제일 안전한 것 -> 가장 위험한 것 순서로 진행

  1. 기본적으로 static_cast를 쓸 것
    • reinterpret_cast<Cat*> 대신 static_cast<Cat*>
      • 만약 Cat이 Animal이 아니라면 컴파일러가 에러를 뱉음
  2. reinterpret_cast를 쓸 것
    • 포인터와 비포인터 사이의 변환
      • 이걸 정말 해야 할 때가 많음
    • 서로 연관이 없는 포인터 사이의 변환은 그 데이터형이 맞다고 정말 확신할 때만 사용할 것
  3. 내가 변경권하니 없는 외부 라이브러리를 호출할 때만 const_cast를 사용할 것

정리

C스타일 캐스팅 대신 C++캐스팅을 쓰는 이유는?

정적 캐스팅

리인터프리트 캐스팅

컨스트 캐스팅

동적 캐스팅

어떤 캐스팅을 써야 하지?