2021 시작

class Rational 
{
private:
	int a, b;
	int sum;
public:
	Rational(int numberator = 0,
		int denominator = 1);

	int numerator() const;
	int denominator() const;
};

우리가 유리수를 나타내는 클래스를 만든다고 치자 그렇다면 덧셈이나 곱셈들의 수치연산을 지원하는것이 좋을것이다.

그리하여 멤버함수로 "operator *()"를 구현하려고 한다.

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

이렇게 구현해 놓고 유리수 곱셈연산을 해 보았다.

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

Rational result = oneHalf * oneEighth;	//가능
result = result * oneEighth;		//가능

그리고 혼합형 수치연산도 해보고 싶어서 시도해 보았다.

result = oneHalf * 2;	//가능
result = 2 * oneHalf;	//에러

시도를 해 보았는데 두 번째 코드가 제대로 동작하지 않는다. 이유가 무엇일까? 위의 코드를 한번 풀어서 봐보자

result = oneHalf.operator*(2);		//가능
result = 2.operator*(oneHalf);		//에러

 

첫 번째 줄어서는 oneHalf의 operator* 함수를 호출하고 오른쪽 값인 2가 Rational(2)로 자동적으로 형변환을 하여 정상적으로 작동한다. 하지만 두 번째 줄은 정수 2가 operator* 함수를 가지고 있을리가 만무하기 때문에 에러가 나는 것이다.

만약 (int,int)생성자를 explicit을 하여 명시호출로 선언하였으면

result = oneHalf * 2;		//에러! (명시호출 생성자에 의해)
							//2를 Rational로 바꿀 수 없다.
                            
result = 2 * oneHalf;		//역시 에러이다. 문제도 같다.

암시적 형변환 자체가 안되므로 두개 다 오류가 날것이다. 하지만 우리가 목적으로 하고 있는 것은 두번째 줄도 정상적으로 동작하게 하는것이다.

 

이번에는 해결 방법을 보자

class Rational 
{
private:
	int num, deno;
	int sum;
public:
	Rational(int numberator = 0,
		int denominator = 1);
						//클래스 안에 operator*가 없다.
	int numerator() const { return num; }
	int denominator() const { return deno; }
};

const Rational operator*(const Rational& lhs,		//비멤버 함수
	const Rational& rhs) 
{
	return Rational(lhs.numerator() * rhs.numerator(),
		lhs.denominator() * rhs.denominator());
}

Rational oneFouth(1, 4);
Rational result;

result = oneFourth * 2;		//가능!
result = 2 * oneFourth;		//가능!

 

이렇게 하면 해결 할 수 있다. friend선언을 하며 간단하게 만들 수 있지만 프렌드 함수는 구지 필요한 것이 아니면 쓰지 말자

나중에 46항목에서 일반화를 하면 좀 달라진다.

 

 

 

이것만은 잊지 말자!

 

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

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading