일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- c언어
- C# delegate
- Houdini
- c#
- Python
- 유니티
- C언어 포인터
- Algorithm
- 플러터
- jupyter
- C++
- Unity
- Data Structure
- vim
- gitlab
- c# winform
- Flutter
- c# 윈폼
- git
- 도커
- 다트 언어
- 깃
- dart 언어
- HTML
- docker
- c# 추상 클래스
- 포인터
- github
- 구조체
- jupyter lab
- Today
- Total
nomad-programmer
[Programming/C++] 전역 함수를 이용한 연산자 오버로딩 본문
연산자 오버로딩에는 다음 두 가지가 있다.
- 첫째, 멤버 함수를 이용한 연산자 오버로딩
- 둘째, 전역 함수를 이용한 연산자 오버로딩
일반적으로 멤버 함수를 이용한 연산자 오버로딩을 사용한다. 멤버 함수를 이용한 연산자 오버로딩을 사용할 수 없을 때는 전역 함수 연산자 오버로딩을 사용한다.
멤버 함수를 이용한 연산자 오버로딩을 사용할 수 없는 경우
이항 연산의 왼쪽 항이 연산자 오버로딩 객체가 아니면 멤버 함수를 이용한 연산자 오버로딩을 이용할 수 없다. 이항 연산의 왼쪽 객체를 기준으로 연산자 오버로딩 멤버 함수를 호출하기 때문이다. 예를 들어 보자.
class Point
{
...
};
int main()
{
Point p1(1, 2), pt2(3, 4);
pt1 + pt2; // pt1.operator+(p2)
return 0;
}
위에서 p1 + p2의 이항 연산은 p1을 this 객체로 멤버 함수를 pt1.operator+(pt2)와 같이 호출한다. 그러므로 왼쪽 항이 자신의 객체(연산자 오버로딩 객체)가 아니라면 아래처럼 멤버 함수를 호출할 수 없으며 전역 함수 연산자 오버로딩을 사용해야 한다.
class Point
{
...
};
int main()
{
Point pt1(1, 2);
k + p1;
// 여기서 k는 연산자 오버로딩 객체가 아니므로 k.operator+(p1) 처럼 호출할 수 없다.
// operator+(k, pt1) 처럼 호출해야 한다.
return 0;
}
연산자 오버로딩은 컴파일러가 p1 == p2;와 같은 코드를 두 가지로 해석한다.
- 멤버 함수로 p1.operator==(p2); 처럼 해석하며, 이것은 p1의 operator==() 멤버 함수를 호출해 p2를 인자로 전달한다.
- 전역 함수로 operator==(p1, p2); 처럼 해석하며, 이것은 전역 함수 operator==()의 인자로 p1와 p2 객체를 각각 전달한다.
멤버 함수를 이용한 연산자 오버로딩
멤버 함수를 이용한 -연산자 오버로딩이다.
#include <iostream>
using namespace std;
class Point {
public:
Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
void Print() const { cout << x << ',' << y << endl; }
int GetX() const { return x; } // x의 getter
int GetY() const { return y; } // y의 getter
const Point operator-(const Point& ref) const {
return Point(x - ref.x, y - ref.y);
}
private:
int x;
int y;
};
int main() {
Point p1(2, 3), p2(5, 5);
Point p3;
p3 = p1 - p2;
p3.Print();
return 0;
}
// 결과
-3, -2
p1 - p2는 p1의 멤버 함수 p1.operator-(p2)를 호출한다. p2는 인자로 전달된다.
전역 함수를 이용한 연산자 오버로딩
다음의 예제는 전역 함수를 이용한 - 연산자 오버로딩이다.
#include <iostream>
using namespace std;
class Point {
public:
Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
void Print() const { cout << x << ',' << y << endl; }
int GetX() const { return x; } // x의 getter
int GetY() const { return y; } // y의 getter
private:
int x;
int y;
};
const Point operator-(const Point& ref1, const Point& ref2) {
return Point(ref1.GetX() - ref2.GetX(), ref1.GetY() - ref2.GetY());
}
int main() {
Point p1(2, 3), p2(5, 5);
Point p3;
p3 = p1 - p2;
p3.Print();
return 0;
}
// 결과
-3, -2
p1 - p2는 전역 함수 operator-(p1, p2)를 호출한다. p1과 p2는 인자로 전달된다. operator-(p1, p2); 이렇게 전달된다.
전역 함수를 이용하면 Point 클래스의 private 멤버인 x, y에 접근할 수 없으므로 getter를 이용하거나 friend 함수를 사용해야 한다.
friend 함수를 사용하는 코드는 다음과 같다.
friend const Point operator-(const Point& ref1, const Point& ref2) const {
return Point(ref1.x - ref2.x, ref1.y - ref2.y);
}
이렇게 게터(getter)나 세터(setter)를 사용하지 않고 x, y에 직접 접근할 수 있다. friend 함수는 캡슐화를 저해하므로 가능하면 getter, setter를 사용하는 방법이 좋다.
friend 키워드
friend에는 함수 friend와 클래스 friend, 두 가지가 있다. 함수나 클래스를 friend로 지정하면, 모든 클래스 멤버(private, protected, public)를 접근 제한 없이 사용할 수 있다. 함수 friend는 다음과 같이 지정한다.
class A {
...
friend void Func();
};
void Func() {
// class A의 모든 멤버를 접근 제한 없이 사용할 수 있다.
}
클래스 friend는 다음과 같이 지정한다.
class A {
...
friend class B;
}
class B {
// class A의 모든 멤버를 접근 제한 없이 사용할 수 있다.
}
'Programming > C++' 카테고리의 다른 글
[Programming/C++] 오버라이딩(overriding) (2) | 2023.01.21 |
---|---|
[Programming/C++] 가상 함수를 사용한 다형성의 구현 (0) | 2023.01.21 |
[Programming/C++] 다중 상속(Multiple Inheritance) (0) | 2023.01.20 |
[Programming/C++] 접근 제어 키워드 (public, protected, private) (0) | 2023.01.20 |
[Programming/C++] 연산자 오버로딩 (0) | 2023.01.19 |