방프리

17.08.22. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목24) 본문

C++/Effective C++

17.08.22. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목24)

방프리 2020. 1. 14. 01:26

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

 

- 클래스를 생성하고 그 클래스에 대한 연산자를 오버라이딩할 때 항상 멤버 함수를 오버라이딩을 해왔습니다.

그로인해 이러한 연산 코드도 가능했죠.

ex)

class Point

{

private:

int x, y;

public :

Point();

~Point();

 

const Point operator*(const Point& arg);

};

 

하지만 이 함수가 모든 곳에 적용이 되진 않습니다. 가령

ex)

Point p1, p2;

 

p2 = 2 * p1; // 에러 발생!

이러한 코드가 있다면 Point 클래스의 재정의 된 *이 아닌 상수 2의 * 연산자가 되어버리기 때문입니다.

즉, 곱셈의 주체가 클래스 객체가 아니라면 아무 소용이 없다는 뜻이죠.

그러면 항상 곱셈의 주체가 되는 객체를 앞에 두면 되지 않느냐라고도 할 수 있지만 

다음의 코드의 상황에서도 오류가 발생합니다.

 

ex)

p2 = p1 * 2; //컴파일은 되지만 제대로 안됩니다.

 

다음 코드가 제대로 동작하지 않는 이유는 바로 암시적 변환 때문입니다.

정수인 2를 Point 클래스로 암시적 변환하기 때문에 데이터가 제대로 들어갈리가 없죠.

해결 방법으로는 암시적 타입 변환에 대해 매개변수가 들어가도록 매개변수 리스트에 들어가게 만들어주면 됩니다.

즉, 이런 코드가 작성될 수 있다는 뜻이죠.

class Rational 

{

....

};

 

const Rational operator* (const Rational& lhs, const Rational& rhs)

{

return Rational( lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator() );

}

 

이렇게 작성될 수 있습니다.

friend 키워드를 통해 작성하는 것도 좋지 않느냐 라는 분들도 계실텐데 데이터의 안전성을 고려한다면

그다지 좋은 방법은 아닙니다. 

이 과정을 통해 필자는 독자들에게 "멤버 함수의 반대는 프렌드 함수가 아닌 비멤버 함수"라는 것을 알려주고

있습니다. 

 

이것만은 잊지말자!

* 어떤 함수에 들어가는 모든 매개변수(this 포인터가 가리키는 객체도 포함해서)에 대해 타입 변환을 해 줄 필요가 있다면, 그 함수는 비멤버이어야 합니다.

Comments