1. 정적 캐스트 (static_cast)

개념:

  • static_cast컴파일 타임에 수행되는 타입 변환 연산자입니다.
  • 기본적으로 안전한 변환에 사용되며, 명시적으로 허용된 변환만 가능합니다.

특징:

  1. 기본 자료형 간의 변환:
    • 예: int에서 float로 변환.
  2. 상속 관계에서 부모-자식 간 변환:
    • 예: Player*Knight* (상속 관계에서의 업캐스팅, 다운캐스팅).
  3. void* 포인터를 다른 타입의 포인터로 변환.

예제: 기본 자료형 간 변환

int hp = 100;
int maxHp = 200;
float ratio = static_cast<float>(hp) / maxHp;

분석:

  1. static_cast<float>(hp)intfloat로 변환.
  2. 안전성:
    • int에서 float로의 변환은 데이터 손실 위험이 없으므로 안전합니다.
    • 컴파일러가 명시적으로 허용된 변환이므로 런타임 오류 가능성이 없습니다.

예제: 상속 관계에서 변환

class Player {};
class Knight : public Player {};

Knight* k = new Knight();
Player* p = k;  // 업캐스팅
Knight* k2 = static_cast<Knight*>(p);  // 다운캐스팅

분석:

  1. Player* p = k;
    • 자식 클래스(Knight*)를 부모 클래스(Player*)로 변환. 업캐스팅.
  2. Knight* k2 = static_cast<Knight*>(p);
    • 부모 클래스(Player*)를 자식 클래스(Knight*)로 변환. 다운캐스팅.
    • 상속 관계가 명확하므로 컴파일러는 변환을 허용.

주의:

  • static_cast런타임 검사를 수행하지 않음.
  • 부모 포인터(Player*)가 실제로 Knight*가 아니면, 변환된 포인터로 잘못된 메모리 접근이 발생할 수 있음.

2. 동적 캐스트 (dynamic_cast)

개념:

  • dynamic_cast런타임 타입 검사(RTTI, Run-Time Type Information)를 수행하며, 상속 관계에서의 안전한 형 변환을 보장합니다.
  • 부모 클래스에서 자식 클래스로의 다운캐스팅 시 사용.

특징:

  1. 상속 관계에서만 사용 가능.
  2. 런타임에 타입이 맞지 않으면 nullptr을 반환.
  3. 가상 함수(virtual)를 가진 클래스에서만 사용 가능.
  4. 성능이 중요한 코드에서는 지양 (런타임 비용 발생).

예제: 안전한 다운캐스팅

class Player { virtual ~Player() {} };
class Knight : public Player {};

Player* p = new Knight();
Knight* k2 = dynamic_cast<Knight*>(p);

if (k2 != nullptr) {
    // 변환 성공
} else {
    // 변환 실패
}

분석:

  1. Player* p = new Knight();
    • Knight 객체를 생성하고 부모 클래스 포인터로 저장.
  2. dynamic_cast<Knight*>(p)
    • 런타임에 p가 실제로 Knight* 타입인지 검사.
    • 타입이 맞지 않으면 nullptr을 반환.
  3. 안전성:
    • 런타임 검사로 인해 잘못된 타입 변환을 방지.

3. 상수 캐스트 (const_cast)

개념:

  • const_castconst 또는 volatile 속성을 제거하거나 추가합니다.
  • 주로 const로 선언된 변수의 수정이 필요할 때 사용.

예제: const 제거

const int x = 10;
int& y = const_cast<int&>(x);
y = 20;  // x의 값을 변경

분석:

  1. const_cast<int&>(x)xconst 속성을 제거하여 int&로 반환.
  2. y = 20;
    • y를 통해 x의 값을 변경.
  3. 주의:
    • const 속성을 제거한 변수의 값을 변경하면 정의되지 않은 동작(UB, Undefined Behavior)이 발생할 수 있음.
    • 실제 메모리가 const로 보호되지 않은 경우에만 안전.

4. 재해석 캐스트 (reinterpret_cast)

개념:

  • 비트 수준에서 데이터를 다른 타입으로 해석.
  • 주로 포인터 타입 변환에 사용되며, 매우 강력하지만 위험함.

예제: 포인터 변환

class Dog {};
Dog* dog = new Dog();
int64_t address = reinterpret_cast<int64_t>(dog);

분석:

  1. Dog* dogDog 객체의 포인터를 저장.
  2. reinterpret_cast<int64_t>(dog)는 포인터를 정수형으로 변환하여 메모리 주소를 저장.
  3. 사용 예:
    • 시스템 프로그래밍, 메모리 매핑 등에서 활용.

예제: 잘못된 사용

class Dog {};
class Cat {};

Dog* dog = new Dog();
Cat* cat = reinterpret_cast<Cat*>(dog);

분석:

  1. reinterpret_cast<Cat*>(dog)Dog 객체를 Cat 포인터로 해석.
  2. 위험성:
    • 두 클래스가 아무런 관계가 없으므로, cat을 통해 잘못된 메모리에 접근하면 프로그램이 충돌.

5. 캐스팅 방법 비교

캐스팅 방법특징사용 예
static_cast컴파일 타임 변환, 안전한 변환만 허용.기본 자료형 변환, 상속 관계의 업캐스팅 및 다운캐스팅.
dynamic_cast런타임 타입 검사 수행, 안전한 다운캐스팅 제공.상속 관계에서 자식 클래스 타입 확인. RTTI 사용.
const_castconst 또는 volatile 속성 제거.const 변수의 수정이 필요할 때 사용.
reinterpret_cast비트 수준에서 데이터 변환. 매우 강력하지만 위험함.포인터 타입 변환, 메모리 주소 저장, 하드웨어 레지스터 접근 등.

profile
李家네_공부방

0개의 댓글