변환 생성자의 조건은 생성자의 인수가 1개다. 기본 자료형들 간의 대입과 암시적인 형변환을 생각하면 쉽게 이해된다. 변환생성자의 역할이 바로 이런 형 변환인데, 변환 생성자의 경우는 명시적으로 사용할 것은 권고 한다. 명시적으로 사용하기 위해서는 explicit 키워드를 생성자에 붙이면 된다. 왜 명시적으로 사용해야 되는지는 몇 가지 예를 보면 쉽게 이해할 수 있다.
변환 생성자
Test(int a)는 변환 생성자다. 이 녀석의 역할은 int형 자료형을 Test형 객체로 변환한다. Test(char s) 또한 변환 생성자다. 마찬가지로 char형 자료형을 Test형 객체로 변환해 준다. 위 코드는 문제가 없이 잘 실행 된다.
그러면 여기서 클래스 내부의 생성자 Test(char s)를 없애면 결과가 어떻게 될지 생각해 보자.
문제 없이 실행이 되지만 결과가 달라진다. 아래와 같이
Test t1('A'); // Test(int a) 생성자가 호출 된다.
'A'의 아스키 코드값은 65므로 F가 출력 된다.
이런 에러의 경우는 전혀 예상할 수가 없다. 왜냐면 기본 자료형의 암묵적 형변환으로 데이타 값 자체는 문제없이 입력된 꼴이 되기 때문이다.
사전에 이련 결과를 차단하기 위해서 explicit 키워드가 필요하다.
explicit 키워드를 생성자 앞에 붙임므로써 암묵적인 형변환을 차단 할 수 있다. 따라서 정말 찾기 힘든 위와 같은 오류(아마 이런 오류는 특별한 에러가 나지 않으므로 영원히 묻힐 수도 있는 오류다. 정밀한 계산을 요하는 장비의 소프트웨어라면 이런 오류는 재앙이다.)
위 코드에서 explicit 키워드를 사용함으로써 다음과 같은 표현도 사용할 수 없다.
Test t = 88;
반드시 Test t(88); 이라고 또는 Test t = (int)88; 이라고 자료형에 대한 명시를 해 줘야 한다.
참고 : explicit 키워드는 c++11이전에는 위와 같은 용도로만(생성자에만) 사용했는데 c++11에서는 사용범위가 더 확장되었다.
좀 더 필요한 사항
변환 생성자에서 암시적 형변환 문제로 explicit 키워드를 사용했지만, 아직 문제가 더 남아 있다. 역 변환의 경우를 고려해 봐야 한다. 사실 위 코드는 역 변환을 할 수 없는 코드(범위 값으로 변경되었기 때문에 원래 값이 사라짐)기 때문에 새로운 예를 들어보자.
간단하게 초를 분과 초 바꾸는 예를 들어보겠다.
제대로 동작을 하는데, 다시 반대로 A객체를 초로 바꿔 출력 하고 싶다면 역 변환이 필요하다. 변환은 캐스팅이므로 역 변환 또한 캐스팅이다. 이를 위해서 캐스트 연산자 오버로딩이 필요하다.
캐스트 연산자 오버로딩
연산자 오버로딩의 경우는 정해진 문법이 있으므로 따로 정리하는 것이 좋다. 이 부분은 나중에 알아보기로 하고
우선 캐스트 연산자 오버로딩 문법은 다음과 같다.
반환형이 없는데 변환 타입 자체가 반환형이므로 따로 반환형을 사용하지 않는다. 물론 내부에는 반환 값이 있어야 하겠다.
초로 캐스팅 변환이 제대로 된다. 이런 변환 함수의 경우도 암시적 변환 문제가 생길 소지가 당연히 있다.(Test 클래스의 객체는 암시적으로 int형으로 사용(변환)될 수 있기 때문이다.) 다음은 이 예다.
위와 같이 B 값에 Test형 객체를 잘못 대입할 경우 아무런 경고도 없이 그냥 대머리가 될 수도 있다.
따라서 이렇게 c++11의 경우 explicit 키워드를 꼭 사용하는 것이 좋다.