아래의 코드를 실행해보자.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
int value1;
TEST()
: value1(0)
{
cout << "생성자 호출" << endl;
}
TEST(int val1)
: value1(val1)
{
value1 = val1;
cout << "생성자 호출 2" << endl;
}
void printValue()
{
cout << value1 << endl;
}
};
void implicitTypeCasting(TEST a)
{
a.printValue();
}
int main(void)
{
implicitTypeCasting(100);
return 0;
}
TEST가 int에 대한 생성자를 제공하기 때문에 implicitTypeCasting 함수에서 묵시적 변환이 발생하였다.
TEST a가 생성자 호출 2를 출력되었으므로 아래의 코드가 실행되었다고 할 수 있다.
implicitTypeCasting(TEST(100));
의도적으로 묵시적 변환을 허용하지 않으려면 explicit 키워드를 사용하면 된다.
class TEST
{
public:
int value1;
...
explicit TEST(int val1)
: value1(val1)
{
value1 = val1;
cout << "생성자 호출 2" << endl;
}
...
};
explicit으로 사용자가 묵시적으로 변환이 일어나게 하는 것을 컴파일 에러를 일으켜서 차단할 수 있다.
int main(void)
{
// implicitTypeCasting(100); // compile error
implicitTypeCasting(TEST(100)); // ok
return 0;
}
위의 코드에 value2를 추가하고 main을 수정하여 test를 printf로 출력해보자.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
int value1;
int value2;
TEST()
: value1(0), value2(0)
{
cout << "생성자 호출" << endl;
}
explicit TEST(int val1, int val2)
: value1(val1), value2(val2)
{
value1 = val1;
cout << "생성자 호출 2" << endl;
}
void printValue()
{
cout << value1 << value2 << endl;
}
};
int main(void)
{
TEST test = TEST(100, 200);
printf("int %d\n", test);
printf("long %lld\n", test);
return 0;
}
먼저 858993459300이 무엇을 의미하는지 알아보자.
계산기 - 프로그래머 모드를 이용하면 858993459300이 메모리에 어떻게 저장되는지 알 수 있다.
100은 아래와 같다.
200은 아래와 같다.
즉 858993459300은
00000000 00000000 00000000 11001000 00000000 00000000 00000000 01100100
= 200 과 100이 메모리에 저장된 상태를 long type으로 읽은 값이다.
printf의 %d는 변수가 뭐든 4바이트를 읽고, %lld는 8바이트를 읽기 때문에 위와 같은 값이 출력되었다.
이제 printf 대신 cout으로 test를 읽어보자.
int main(void)
{
TEST test = TEST(100, 200);
printf("int %d\n", test);
printf("long %lld\n", test);
cout << test << endl;
cout << (int)test << endl;
return 0;
}
<< 연산자로 test를 읽을 방법이 없으니 compile 에러가 난다.
int로 강제로 형변환 하면 printf 처럼 읽을 수 있을 것 같지만, TEST는 int가 아니므로 형변환이 불가능하다.
그런데 c++에서는 이런 형변환 연산자도 오버로딩 할 수 있다.
여기서는 int로 강제 형변환 할 경우 value1, 2를 곱한 값을 return 하도록 하였다.
class TEST
{
public:
int value1;
int value2;
...
operator int() { return value1 * value2; }
};
cout을 통해 출력한 test와 (int)test가 100 x 200 = 20000으로 출력되는 것을 알 수 있다.
하지만 test도 20000이 출력되는 이유는 여기서도 묵시적 변환이 일어나기 때문이다.
다시 type casting int에 explicit을 명시해주면 묵시적 변환이 일어나지 않는다.
explicit operator int() { return value1 * value2; }
(int)test에 대한 에러는 사라졌고, 이전과 마찬가지로 << 연산자에 대한 compile error가 발생한다.
참고로 (int) test는 c 스타일의 강제 casting이므로 c++에서는 static_cast를 사용하는 것이 좋다.
static_cast는 컴파일 타임에서 가능한 형변환인지 체크한다.
#include <stdio.h>
#include <iostream>
using namespace std;
class TEST
{
public:
int value1;
int value2;
TEST()
: value1(0), value2(0)
{
cout << "생성자 호출" << endl;
}
explicit TEST(int val1, int val2)
: value1(val1), value2(val2)
{
value1 = val1;
cout << "생성자 호출 2" << endl;
}
void printValue()
{
cout << value1 << value2 << endl;
}
explicit operator int() { return value1 * value2; }
};
int main(void)
{
TEST test = TEST(100, 200);
printf("int %d\n", test);
printf("long %lld\n", test);
//cout << test << endl;
//cout << (int)test << endl; // c style
cout << static_cast<int>(test) << endl;
return 0;
}
'개발 > C, C++' 카테고리의 다른 글
C++ - virtual / override 키워드 (0) | 2021.08.25 |
---|---|
C++ - 가상 소멸자 (Virtual Destructor) (0) | 2021.08.23 |
C++ - virtual, type casting (0) | 2021.08.15 |
C++ - virtual 키워드 (0) | 2021.08.14 |
C++ - 복사 생성자를 이용한 객체의 깊은 복사 (Deep Copy using Copy Constructor) (0) | 2021.08.10 |
댓글