코드를 한 줄씩 자세히 분석하여 설명드리겠습니다. 이 예제는 C++의 다양한 형변환 규칙과 형변환에 따른 동작 방식을 다루고 있습니다.
void func(float f) { }
void func(Parent* parent) { }
void func(const Child& child) { }
func
함수는 서로 다른 파라미터 타입을 받는 오버로드된 세 가지 버전을 정의합니다.func(float f)
: float
타입의 인자를 받습니다.func(Parent* parent)
: Parent
포인터를 받습니다.func(const Child& child)
: Child
클래스의 상수 참조를 받습니다.func
함수들은 전달된 인자의 타입에 따라 호출됩니다.class Test
{
public:
explicit operator bool() const
{
return true;
}
};
Test
클래스에 bool
타입으로의 변환 연산자를 정의했습니다.explicit
키워드를 사용하여 명시적 변환만 허용합니다. 즉, Test
객체를 bool
로 변환할 때 자동 변환되지 않으며, 명시적으로 호출해야 합니다.class Parent { };
class Child : public Parent { };
Parent
클래스와 이를 상속받는 Child
클래스를 정의했습니다.Child
는 Parent
클래스를 공개(public) 상속하며, 이를 통해 자식 클래스에서 부모 클래스 타입으로의 암시적 형변환이 가능합니다.main
함수int main()
{
float f = 1;
func(1);
float f = 1;
에서 int
값 1
이 float
로 암시적 형변환됩니다.func(1);
은 1
을 float
로 암시적 변환하여 func(float f)
버전을 호출합니다. char ch0 = 'a';
int num0 = ch0;
char ch0 = 'a';
는 문자 'a'
를 저장합니다.int num0 = ch0;
는 char
를 int
로 암시적 형변환하며, 이는 promotion 또는 확대 변환이라고 불립니다. int num1 = 1000;
char ch1 = num1;
char ch1 = num1;
은 int
를 char
로 암시적 변환하는 demotion(축소 변환)입니다. char
의 크기보다 큰 값을 저장하려는 경우 데이터 손실이 발생할 수 있습니다. const int num2 = 10;
char ch2{ num2 };
char ch2{ num2 };
에서 {}
를 사용한 통합 초기화는 축소 변환이 필요한 경우 컴파일 타임에 오류를 발생시킵니다.num2
가 char
에 맞는 값이므로 정상적으로 초기화됩니다. unsigned short s0 = 40000;
cout << s0 + s0 << endl;
cout << typeid(s0 + s0).name() << endl;
s0 + s0
에서 unsigned short
값이 int
로 promotion되어 계산됩니다. typeid
를 통해 결과 타입을 확인할 수 있습니다. unsigned int i0 = 4100000000;
cout << i0 + i0 << endl;
cout << typeid(i0 + i0).name() << endl;
i0 + i0
에서 오버플로우가 발생합니다. unsigned int
타입으로 남으며, 결과 값이 unsigned int
범위를 초과해 오버플로우됩니다. unsigned int i1 = 10;
int i2 = -110;
cout << i0 + i2 << endl;
cout << typeid(i0 + i1).name() << endl;
i0 + i2
에서 unsigned
가 포함된 연산은 결과가 항상 unsigned
가 됩니다. 따라서 int
값이 unsigned int
로 암시적 변환되어 언더플로우가 발생할 수 있습니다. long long l0 = 10;
cout << l0 + i1 << endl;
cout << typeid(l0 + i1).name() << endl;
l0 + i1
에서 i1
은 long long
타입으로 암시적 변환되어 결과가 long long
이 됩니다. float f = 1.f;
unsigned long long ull = 10ULL;
cout << typeid(f + ull).name() << endl;
f + ull
에서 unsigned long long
은 float
타입으로 변환되어 실수 연산이 수행됩니다.long double > double > float
).Test
객체의 암시적 변환 Test t;
bool b = t;
if (t) {}
while (t) {}
t ? 1 : 2;
!t;
t && true;
false || t;
Test
객체 t
를 bool
로 암시적 변환하려 할 때 explicit
키워드로 인해 bool b = t;
는 컴파일되지 않습니다.if
, while
, 삼항 연산자, 논리 연산자 등에서는 암시적 변환이 허용됩니다.const
형변환 int a = 1;
const int& b = a;
const int* c = &a;
int a
는 const int&
또는 const int*
로 암시적 형변환됩니다. 이는 상수화(const-casting)라고 하며, 원본 값 a
의 수정은 허용되지 않습니다. Child c;
Parent* p0 = &c;
Parent& p1 = c;
func(&c);
func(c);
Child
타입의 객체 c
를 Parent*
또는 Parent&
타입으로 암시적 변환할 수 있습니다. 이를 통해 부모 타입으로 형변환이 이루어집니다. (Child*)c;
(Child*)(c);
}
Child
객체로의 명시적 형변환을 보여줍니다.