콘텐츠로 이동

캐스팅 (Casting)

static_cast<float>(double_value) 같은 C++ 스타일 캐스트를 쓰거나, int64_t y = int64_t{1} << 42처럼 산술 타입을 변환할 때는 중괄호 초기화를 쓰세요. void로의 캐스트가 아닌 한 (int)x 같은 캐스트 형식을 쓰지 마세요. T(x) 같은 캐스트 형식은 T가 클래스 타입일 때만 쓸 수 있습니다.

정의:

C++는 캐스트 연산의 종류를 구분하는, C와는 다른 캐스트 체계를 도입했습니다.

장점:

C 캐스트의 문제는 그 연산이 모호하다는 점입니다. 어떤 때는 변환을 하고(예: (int)3.5), 어떤 때는 캐스트를 합니다(예: (int)"hello"). 중괄호 초기화와 C++ 캐스트는 이런 모호함을 피하는 데 도움이 되는 경우가 많습니다. 게다가 C++ 캐스트는 찾아볼 때 눈에 더 잘 띕니다.

단점:

C++ 스타일 캐스트 문법은 장황하고 번거롭습니다.

결정:

일반적으로 C 스타일 캐스트는 쓰지 마세요. 명시적인 타입 변환이 필요하다면 대신 아래의 C++ 스타일 캐스트를 쓰세요. 일부는 표준 C++ 언어의 일부이고, 일부는 absl/base/casts.h에 정의되어 있습니다. 올바르게 적용되는 첫 번째 것을 사용하세요.

  • 산술 타입을 변환할 때는 중괄호 초기화를 쓰세요(예: int64_t{x}). 변환으로 정보가 손실될 수 있으면 코드가 아예 컴파일되지 않으므로 가장 안전한 방법입니다. 문법도 간결합니다.
  • 클래스 타입으로 명시적으로 변환할 때는 함수 스타일 캐스트를 쓰세요. 예를 들어 static_cast<std::string>(some_cord)보다 std::string(some_cord)를 선호하세요.
  • 타입 계층을 따라 위로 안전하게 캐스트할 때는 absl::implicit_cast를 쓰세요. 예를 들어 Foo*를 SuperclassOfFoo*로 캐스트하거나 Foo*를 const Foo*로 캐스트하는 경우입니다. C++가 보통은 이를 자동으로 해 주지만, ?: 연산자를 쓸 때처럼 명시적인 업캐스트가 필요한 상황도 있습니다.
  • 값 변환을 하는 C 스타일 캐스트에 해당하는 용도로, 또는 클래스에서 그 상위 클래스로 포인터를 명시적으로 업캐스트해야 할 때, 또는 상위 클래스에서 하위 클래스로 포인터를 명시적으로 캐스트해야 할 때는 static_cast를 쓰세요. 마지막 경우에는 그 객체가 실제로 하위 클래스의 인스턴스인지 확실히 해야 합니다.
  • 상위 클래스에서 하위 클래스로 포인터를 캐스트할 때는 absl::down_cast를 쓰세요. 그 객체가 실제로 하위 클래스의 인스턴스인지 확실히 해야 합니다.
  • const 한정자를 제거할 때는 const_cast를 쓰세요(const 참조).
  • 포인터 타입을 정수나 void*를 포함한 다른 포인터 타입으로, 또는 그 반대로 안전하지 않게 변환할 때는 reinterpret_cast를 쓰세요. 자신이 무엇을 하는지 알고 앨리어싱 문제를 이해할 때만 쓰세요. 또한 (캐스트 없이) 포인터를 역참조한 다음 그 결과 값을 std::bit_cast로 캐스트하는 방법도 고려해 보세요.
  • 같은 크기의 다른 타입으로 값의 원시 비트를 해석할 때는 std::bit_cast를 쓰세요. double의 비트를 int64_t로 해석하는 것처럼, 이를 타입 퍼닝(type pun)이라고 합니다.

dynamic_cast 사용에 대한 지침은 RTTI 절을 참조하세요.


옮긴이 풀이

핵심: C 스타일 캐스트 대신 C++ 캐스트·중괄호 초기화

(int)x 같은 C 스타일 캐스트는 쓰지 마세요(void 캐스트 제외). 동작이 모호하고(변환인지 재해석인지 불분명) 검색으로 찾기도 어렵습니다. 대신 의도가 드러나는 C++ 캐스트를 쓰세요.

static_cast<float>(double_value);  // C++ 스타일 캐스트
int64_t y = int64_t{1} << 42;      // 산술 변환은 중괄호 초기화

상황별 선택 (맞는 첫 번째를 사용)

목적 사용
산술 타입 변환 중괄호 초기화 int64_t{x} (정보 손실 시 컴파일 오류 → 가장 안전)
클래스 타입으로 변환 함수 스타일 std::string(some_cord)
계층 안전 업캐스트 absl::implicit_cast
다운캐스트(타입 보장됨) absl::down_cast
const 제거 const_cast
안전하지 않은 포인터 재해석 reinterpret_cast (앨리어싱을 이해할 때만)
같은 크기 타입의 비트 재해석 std::bit_cast (타입 퍼닝)

dynamic_cast 사용 지침은 RTTI 절을 참조하세요.