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

수민이슈·2023년 3월 27일
0

Effective C++

목록 보기
24/30
post-thumbnail

스콧 마이어스의 Effective C++을 읽고 개인 공부 목적으로 요약 작성한 글입니다!

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


🖊️ 매개변수의 타입 변환

매개변수의 암시적 변환

생성자를 explicit으로 선언하지 않으면 암시적 변환을 허용해준다.

class Rational {
public:
	Rational (int numerator = 0, int denominator = 1);
    
    int numerator() const;
    int denominator() const;
    
private:
	...
};

이런 유리수 클래스가 있다고 하면,
생성자를 explicit으로 선언하지 않았으니까
int에서 Rational로 암시적 변환을 허용해준다.

유리수 클래스니까 곱셈 연산을 지원하도록 하고 싶으니
구현해보자

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

이렇게 하면

Rational oneEight(1, 8);
Rational oneHalf(1, 2);

Rational result = oneHalf * oneEight;			// OK

result = result * oneHalf;						// OK

result = oneHalf * 2;							// OK

result = 2 * oneHalf;							// ERROR

이런 상황이 펼쳐진다.
당연히 Rational * Ratinal은 가능하고
Rational * int는 int를 Rational로 암시적으로 변환해줘서 가능하다.

즉, result = oneHalf * 2

result = oneHalf.opeator*(2);

를 의미하고,
암시적인 변환을 허용하기 때문에

const Rational temp(2);
result = oneHalf * temp;

이 되는거다.

당연히 된다.

근데 result = 2 * oneHalf;

result = 2.opeator*(oneHalf);

를 의미하는데
2는 정수.
정수에는 operator*가 구현되어 있지 않으니
컴파일에러가 뜰거다.
비멤버 버전의 operator*도 없을거다.
현재 int와 Rational의 비멤버 operator는 안해줬으니까.

명시호출 생성자라면?

만약 Rational 생성자가 explicit으로 선언된 명시 호출 생성자라면
result = oneHalf * 2
result = 2 * oneHalf
둘 다 컴파일되지 않았을거다.

암시적 타입 변환은 매개변수 리스트에 있는 매개변수만 가능하다

매개변수에 대해 암시적 타입 변환을 하려면 매개변수 리스트에 있어야 한다

호출되는 멤버함수를 갖고 있는 (this가 가리키는) 객체에 해당하는 매개변수에는 암시적 변환이 먹히지 않는다.

멤버함수를 호출하는 그 객체는 암시적 변환이 되지 않는다는거다.
result = 2 * 3이면
result = 2.opeator*(3)이잖아
3은 Rational로 암시적 변환 될 수도 있지만
opeator* 멤버함수를 호출하는 객체인 2는 Rational로 암시적변환될 수 없다는거다.

그래서

operator*를 비멤버함수로 만들어보자


🖊️ 비멤버 함수로 매개변수의 암시적 타입 변환

operator*을 비멤버 함수로 만들어서
모든 인자에 대해 암시적 타입 변환을 할 수 있도록 해주자

class Rational {
	...
};

const Rational opeator* (const Rational& lhs, const Rational& rhs) { ... };

Rational oneFourth(1,4);
Rational result;

result = oneFourth * 2;					// OK
result = 2 * oneFourth;					// OK

ㅇㅋ??
이렇게 비멤버 함수로 만들면
lhs, rhs 모든 인자에 대해 암시적 타입 변환을 해줄 수 있다.
그래서 자연스럽게
가능하다
헤헤


🖊️ 멤버함수의 반대는 "비멤버 함수"

프렌드 함수는 멤버함수의 반대가 아니에요

멤버함수의 반댓말은 프렌드 함수가 아니다.
프렌드 함수는 피할 수 있으면 피하자.

위 opeator*는 Rational의 public 인터페이스만을 써서 구현할 수 있으므로
friend함수가 아니라 비멤버 함수로 만들어야 한다.


😊

C++시간에 제일 열심히 공부했던 부분..!!
연산자 오버로딩에서 제일 흥미로웠던 부분이다
1학년때 배웠던건데 아직도 재밌어..
explicit 생성자에 대해 확실히 이해할 수 있었다
굿.

0개의 댓글