열렬히.뛰기

여러가지 형변환

Language > 프로그래밍 언어 > C++ > Cpp : 기초 > 여러가지 형변환

기존 C언어에서의 형변환은 다음과 같다.

c
// 묵시적 형변환 (좁은 단위 -> 넓은 단위)
int a = 5;
long long b = a;


// 명시적 형변환 (사용자가 직접 타입을 명시)
int c = (int) b;

그러나 이러한 형변환은 cpp에서 오류를 일으킬 수도 있다.

  1. c++은 객체를 쓴다. 객체 역시 타입이 존재한다.
  2. 객체 간 형변환, 포인터와 객체 간 형변환 등 여러가지 형변환들을 보장할 방법이 있는가?

그래서 다음과 같은 4가지 형변환을 추가적으로 지원한다.

1. static cast

왜 정적 캐스팅인가? 컴파일 시에 캐스팅을 하므로.

cpp
b = static_cast<int> a;
  • 컴파일 시 타입 변환을 확인한다.
  • 기본 자료형 간의 형변환도 허용한다.
  • 형변환이라는 것이 근본적으로 가능한지 확인해줌.
  • 상속 관계에 있는 클래스 타입의 변환은 허용. 단 안전하지 않을 수 있음.
    • 부모 타입 → 자식 타입 : 다운캐스팅 (안전하지 않음. 부모를 자식으로 바꿀 때, 자식이 가지고 있는 것은 부모가 가지고 있지 않을 수 있음)
    • 자식 타입 → 부모 타입 : 업캐스팅 (안전)

2. reinterpret cast

일반적으로 허용하지 않는 형변환을 강제로 진행.

cpp
// Human과 Animal은 전혀 관련이 없는 클래스

Animal* animal = new Animal();
Human* human = new Human();
human = static_cast<Human*>(animal); // 컴파일에러.
human = reinterpret_cast<Human*>(animal); // 형변환 허용!

주로 라이브러리 속 함수의 자료형을 형변환할 때 쓰임.

ex. 구조체 멤버 하나하나 옮기는 대신 사용자가 정의한 행렬 구조체로 한번에 형변환

3. const cast

const나 volatile이 붙은 자료형의 속성을 제거할 때 사용.

cpp
const std::string any = "Hello";
std::string str = const_cast<std::string>(any);

라이브러리의 함수 인자가 const기능이 없고 const 속성이 존재하는 변수를 넘기지 못하는 경우 주로 사용한다. 다만, 역시 위험하므로 함부로 쓰는 것은 자제해야 함.

4. dynamic cast

왜 동적 캐스팅인가? 런타임 시(=프로그램 실행 시)에 캐스팅을 하므로

cpp
// Dog와 Cat은 Animal이라는 같은 부모를 가지고 있음.

int main()
{
    Animal* cat = new Cat();
 
    Dog* dog = dynamic_cast<Dog*>(cat);
    delete cat;
}

언제 쓸 수 있는가?

  • 포인터 또는 참조형을 캐스팅할 때만 사용가능
    • 부모 클래스와 자식 클래스 간 변환에 사용
  • 하나 이상의 가상함수가 무조건 필요
  • 부모형 → 자식형이 안되면, NULL을 반환.
    • 다운캐스팅 safe 라고 한다.

가능한 이유 : RTTI (Runtime type Indormation)

  • 실시간 타입 정보
  • 가상함수가 있는 클래스에서만 작동. 클래스의 타입 관련 정보가 vtable에 같이 저장되기 때문
  • 제대로 동작하기 위해서는 모든 클래스에 타입과 관련된 정보를 작성해야 함
    • 프로그램이 느려지고 용량이 커지는 문제가 있음.
    • 이 기능을 끌 수도, 켤 수도 있음.