일지

Effective C++...44

niamdank 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 외의 접근 권한을 부여한다는 뜻은 아니다.