이 전에는 연산자 오버로딩을 멤버 함수로 만드는 방법을 소개했고 이번에는 전역 연산자 함수를 만드는 것을 소개하도록 하겠다.
전역 연산자 함수는 말 그대로 전역 함수인데 연산자를 오버로딩하며 클래스의 외부에 존재하며 클래스의 객체를 받아들인다.
#include <iostream>
class Num
{
friend const Num operator+(const Num&, const Num&);
private:
int x;
public:
Num() {}
Num(int _x) : x(_x)
{}
// const Num operator+(const Num& right) const
// {
// return Num(x + right.x);
// }
void outNum(void)
{
std::cout << x << std::endl;
}
};
const Num operator+(const Num& n1, const Num& n2)
{
return Num(n1.x + n2.x);
}
int main(void)
{
Num A(3), B(4);
Num C = A + B + A;
C.outNum();
A.outNum();
B.outNum();
return 0;
}
위의 예제를 보면 실행 결과는 완전히 동일하다.
여기서 눈여겨 볼 점은 class 내부에서 함수를 friend로 지정했다는 것이다. 이 말은 이 함수는 객체끼리 덧셈을 하기 위해 모든 멤버를 자유롭게 읽을 수 있어야 한다.
그럼 멤버 연산자 오버로딩과 전역 연산자 오버로딩의 차이점은 뭘까?
바로 함수의 원형에 차이가 있다는 것이다.
1. 멤버 연산자 함수 - A.operator+(B)
2. 전역 연산자 함수 - operator+(A, B);
우선 인수의 개수가 완전히 다르다는 것을 볼 수 있다.
그리고 이 함수는 전역함수이기 때문에 this가 존재하지 않는다.
인수의 개수가 다르다는 것은 다른 형태로도 변형이 가능하다는 건데 이것은 객체와 기본형의 연산을 할 때도 이용된다.
아래의 예시를 보도록 하자.
const Num operator+(int s) const
{
return Num(x + s);
}
B = A + 3;
B = A.operator+(3);
B = 3 + A; // 불가능
멤버 함수에 operator+를 저렇게 오버로딩을 하게 된다면 A + 3과 같이 기본 연산자하고도 더할 수 있다.
왜냐하면 사실 A.operator+(3)과 같기 때문이다.
하지만 B = 3 + A는 어떻게 해결할까?
순서상으로 3.operator+(A)가 되어야 할 것 같지만 기본형의 사칙연산 오버로딩은 컴파일 단계에서 막혀있다.
즉, 멤버 연산 오버로딩으로는 힘들어 보인다.
이때 사용하는 것이 전역 연산자 함수를 이용하는 것이다.
class Num
{
friend const Num operator+(int s, const Num&);
private:
int x;
public:
Num() {}
Num(int _x) : x(_x)
{}
};
const Num operator+(int s, const Num& n)
{
return Num(s + n.x);
}
3 + A; // 가능
근데 굳이 이렇게 하지 않고 우회하는 방법도 있기는 하다.
// 전역 함수에서 멤버 연산자로 우회하기
const Num operator+(int s, const Num& n)
{
return n + s;
}
// 멤버 연산자 함수가 전역 연산자 함수로 중계하기
const Num operator+(int s) const
{
return s + *this;
}
이렇게 우회하는 이유는 코드의 불필요한 중복을 막기 위해서도 있다.
요약하자면 타입이 다른 객체끼리 연산할 때는 교환 법칙이 성립할 수 있도록 전역 연산자 함수를 제공해야 하며 이 함수가 객체 내부의 멤버를 읽을 수 있도록 프렌드 선언을 적절히 활용해야 한다.
http://www.soen.kr/lecture/ccpp/cpplec.htm
C/C++ 강좌
www.soen.kr
C++ 상속 (0) | 2023.08.07 |
---|---|
C++ 다양한 연산자 오버로딩의 예시 (0) | 2023.08.05 |
C++ 연산자 함수 (0) | 2023.08.05 |
C++ 상수 멤버, const (0) | 2023.08.05 |
C++ 정적 멤버, static (0) | 2023.08.05 |