코드를 한 줄 한 줄 자세히 분석하여 설명드리겠습니다. 이 예제는 static_cast
를 활용한 다양한 형변환을 다루고 있습니다.
class ClassA {};
class ClassB {};
ClassA
와 ClassB
는 변환 테스트용 빈 클래스를 정의한 것입니다.enum class TypeA
{
A, B, C
};
enum class TypeB
{
A, B, C
};
TypeA
와 TypeB
를 정의했습니다. 각각 A
, B
, C
라는 값이 있으며, 열거형 간 변환을 static_cast
로 수행해 볼 수 있습니다.Test
클래스class Test
{
public:
Test(int num) {}
explicit Test(int num0, int num1) {}
operator bool() const
{
return true;
}
explicit operator double() const
{
return 1.2;
}
};
Test
클래스는 다양한 변환을 테스트하기 위해 두 개의 생성자와 형변환 연산자(operator bool()
와 operator double()
)를 정의합니다.explicit
키워드를 통해 두 번째 생성자와 operator double()
을 명시적 변환으로 제한하여, 직접 호출하지 않으면 암시적 변환이 일어나지 않도록 했습니다.class Parent {};
class Child : public Parent {};
Parent
와 이를 상속받는 Child
클래스를 정의했습니다. 이를 통해 상속 관계에서의 다운캐스팅을 시도할 수 있습니다.main
함수 분석static_cast
비교float f = 1.1f;
int* i0 = (int*)&f; // C 스타일 캐스트: float 포인터를 int 포인터로 변환 (위험할 수 있음)
int* i1 = static_cast<int*>(&f); // 컴파일 오류 발생
float
타입 변수 f
의 주소를 int*
타입으로 변환하려고 합니다.(int*)&f
는 이 변환을 허용하지만, 위험한 방식입니다. 이는 원래 타입이 아닌 int*
로 접근하는 동작이기 때문입니다.static_cast<int*>(&f)
는 컴파일러에서 허용되지 않습니다. static_cast
는 호환되지 않는 포인터 타입 간 변환을 막아주기 때문에 컴파일 오류가 발생합니다.ClassA a;
ClassB* b = (ClassB*)&a; // C 스타일 캐스트는 허용됨
//ClassB* b = static_cast<ClassB*>(&a); // 컴파일 타임에 오류
ClassA
의 인스턴스를 ClassB*
로 변환하려고 합니다.(ClassB*)&a
는 허용하지만, 메모리 안전성을 보장하지 않는 위험한 변환입니다.static_cast<ClassB*>(&a)
는 호환되지 않는 타입 간 변환을 막기 때문에 컴파일 타임 오류가 발생합니다.static_cast
로 열거형과 정수 간 변환TypeA type0 = static_cast<TypeA>(0); // 정수를 TypeA로 변환
TypeB type1 = static_cast<TypeB>(type0); // 다른 enum끼리 변환 가능
static_cast
를 사용하여 int
값을 TypeA
열거형으로 변환합니다. 열거형 값과 정수는 호환되므로 가능합니다.type0
을 TypeB
로 변환할 때도 static_cast
를 사용하며, 열거형 간 변환도 가능합니다.Test
객체 생성Test t0 = static_cast<Test>(1); // 변환 생성자 호출
Test t1 = static_cast<Test>(1, 2); // 컴파일 에러: 명시적 생성자
static_cast<Test>(1)
은 첫 번째 생성자 Test(int)
를 호출하여 객체를 생성합니다.static_cast<Test>(1, 2)
는 explicit
로 정의된 두 번째 생성자 Test(int, int)
를 호출하려고 합니다. explicit
생성자는 암시적 형변환이 금지되어 있으므로, static_cast
로는 호출할 수 없고 컴파일 에러가 발생합니다.bool b0 = static_cast<bool>(t0); // bool 형변환 연산자 호출
double d0 = static_cast<double>(t1); // double 형변환 연산자 호출
static_cast<bool>(t0)
는 operator bool()
을 호출하여 bool
타입으로 변환합니다.static_cast<double>(t1)
은 explicit operator double()
을 호출합니다. explicit
이라도 static_cast
를 통해 명시적 변환을 허용합니다.Child c;
Parent& p0 = c;
Child& c0 = static_cast<Child&>(p0); // 부모 -> 자식 다운캐스팅 (가능하지만 위험할 수 있음)
Parent& p0 = c;
는 자식 Child
타입을 부모 Parent
타입 참조로 변환하는 암시적 업캐스팅입니다.static_cast<Child&>(p0)
는 부모를 자식으로 다운캐스팅하는 예로, 상속 관계가 성립하므로 컴파일되지만, 런타임 시 실제로 p0
가 Child
객체를 가리키고 있지 않다면 정의되지 않은 동작을 일으킬 수 있습니다.Parent p1;
Child& c1 = static_cast<Child&>(p1); // 컴파일은 되지만 런타임에서 정의되지 않은 동작
Parent
객체 p1
를 Child&
로 다운캐스팅했습니다. p1
은 실제로 Child
타입이 아니기 때문에, 런타임에서 심각한 오류가 발생할 수 있습니다.dynamic_cast
를 사용하는 것이 더 안전하며, 잘못된 캐스팅을 런타임에 잡아낼 수 있습니다. dynamic_cast
는 타입 안전성을 검사하기 때문에 이런 상황에서 예외를 발생시킬 수 있습니다.