책 정리/Effective C++ 3rd

항목 24. 타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자

ocean20 2020. 1. 10. 11:36

1. 타입변환 예시

이전 내용에서 암시적 타입변환을 지원하는 것은 좋지 않다.라는 내용을 기억할 있다.

하지만 가장 흔한 예외 하나가 숫자 타입을 만들때이다.

class Rational {
public :
  Rational(int numerator = 0, int denominator = 1); //암시적 변환을 위해 explicit을 쓰지 않음
  int numerator() const;
  int denominator() const;

private :
  ...
};

*풀이

  (1) 유리수 클래스이다.

  (2) operator * 코드 클래스 내부에 써주는게 좋을 같다는 판단이 나온다. 밑에서 확인해보자.

 

2. 클래스 내부에 operator * 작성

class Rational {
public:
  …
  const Rational operator*(const Rational& rhs) const;
};

...
Rational oneEighth(1,8);
Rational oneHalf(1,2);
Rational result = oneHalf * 2; // 정상코드
result = 2 * oneHalf;          // 에러코드
...

 

*풀이

  - 정상코드 : operator* 매개변수에 2 대입하면 암시적 변환으로 임시객체 Rational 만들어져 문제없다.

  - 에러코드 : int 2 opeartor * 매개변수리스트에는 Rational 타입이 없다. ->  에러발생 -> 컴파일러는 호환가능한 비멤버버전의 operator* 찾게된다.

 

* 결론

  - this 가리키는 객체에 해당하는 암시적 매개변수리스트에 동일한 타입이 없다면, 암시적 변환이 먹히지 않는다.

   (ex. int operator * 매개변수에는 Rational 타입이 없다. -> 암시적 변환 불가능함)

 

3. 해결방법

class Rational{
…
};

const Rational operator*(const Rational& lhs, const Rational& rhs)  // 비멤버 함수
{
 return Rational(lhs.numerator() * rhs.numerator(),
                 lhs.denominator() * rhs.denominator());  // Rational의 public 멤버만 사용해서 연산이 가능하다.
}; 

* 풀이

  - 비멤버버전의 operator* 코드를 작성하였다. ( 모든 매개변수에 대한 타입 변환을 위해 )

  - 굳이 friend 쓸필요없다.. 주석처럼 Rational public 멤버만으로 사용가능하므로..

 

요약정리

  (1) 어떤함수에 들어가는 모든 매개변수(this 포인터가 가리키는 객체포함) 대해 타입 변환이 필요하다면, '비멤버함수' 구성해라