캐스팅 (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++ 캐스트를 쓰세요.
상황별 선택 (맞는 첫 번째를 사용)¶
| 목적 | 사용 |
|---|---|
| 산술 타입 변환 | 중괄호 초기화 int64_t{x} (정보 손실 시 컴파일 오류 → 가장 안전) |
| 클래스 타입으로 변환 | 함수 스타일 std::string(some_cord) |
| 계층 안전 업캐스트 | absl::implicit_cast |
| 다운캐스트(타입 보장됨) | absl::down_cast |
| const 제거 | const_cast |
| 안전하지 않은 포인터 재해석 | reinterpret_cast (앨리어싱을 이해할 때만) |
| 같은 크기 타입의 비트 재해석 | std::bit_cast (타입 퍼닝) |
dynamic_cast 사용 지침은 RTTI 절을 참조하세요.