-
Effective C++...44일지 2022. 8. 22. 08:51
타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자
생성자를 통한 암시적 변환은 컴파일러에게 고려되지 않는다
다음과 같이 생성자에서 암시적 형 변환을 하던 클래스를 템플릿으로 만들면 operator*에 사용되는 T가 무엇인지 알 수 없기 때문에 컴파일 에러가 발생하게 된다.
template<typename T>
class Rational {
public:
Rational(const T& numerator = 0, const T& denominator = 1);
const T numerator() const;
const T denominator() const;
};
template<typename T>
const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs)
{ ... }
Rational<int> oneHalf(1, 2);
Rational<int> result = oneHalf * 2; // 컴파일 에러 발생!
컴파일 에러 발생하는 구간에서 oneHalf는 정상적으로 진입하지만 두 번째 인자인 2는 int가 되어 암시적으로 Rational<int>가 될 수 있지만 컴파일러는 이러한 암시적 변환을 신경 쓰지 않기에 에러가 발생한다.
클래스 안에 비멤버 함수를 사용
클래스 안에 비멤버 함수를 넣는 방법은 friend밖에 없기 때문에 friend함수를 이용해 operator*를 구현하면 위의 코드가 정상적으로 실행되게 된다.
template<typename T>
class Rational {
public:
// 클래스 내부에 선언 및 정의를 해줘야 한다.
friend const Rational Operator*(const Rational& rhs, const Rational& lhs)
{
return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * hrs.denominator());
}
};
※ friend 함수로 선언했다고 public 외의 접근 권한을 부여한다는 뜻은 아니다.