연산자 오버로딩


 연산자 오버로딩이란 내가 만든 사용자 정의 타입(class나 struct)에 관한 연산자를 정의하여 좀더 편하게 사용할 수 있게 만든 C++의 문법적 기능의 말한다. 


 문법

1
2
3
4
[리턴형] operator[연산자]( [연산 인자] ) {
//연산하는데 들어가는 로직
}
 
cs

example 1)

1
2
3
4
5
6
struct point {
    int x, y;
};
bool operator==(point a, point b) {
    return a.x == b.x && a.y == b.y;
}
cs

example 2)

1
2
3
4
5
6
7
struct point {
    int x, y;
    bool operator==(point b) {
           return x == b.x && y == b.y;
    }
};
 
cs


단항 연산자 오버로딩이항 연산자 오버로딩

 이 두가지 분류는 항의 갯수에 따라 단항 연산자 오버로딩인지, 다항 연산자 오버로딩인지가 정해진다. 오버로딩할 연산자의 항의 개수는 각각의 연산자들의 원래 항의 개수와 정확히 일치한다. 예를들어 /연산은 이항연산자 이므로 이항 연산자 오버로딩 해야하고 !는 단항 연산자 이므로 단항 연산자 오버로딩을 해야한다. 


더 알아 보기

이것 이외에도 아주 특이한 친구들이 몇몇 존재하는데 바로 ++나 --이다. 이 두가지 연산자를 오버로딩하는 방법에 관해서는 구글링 해보도록 하자. 현재 포스팅에서 다루기에는 너무 세세하게 들어간 것 같다.  

 
단항 연산자와 이항 연산자를 오버로딩한 모습은 아래와 같은데 -의 경우 단항연산자로도 쓰이고 이항 연산자로도 쓰이므로 좋은 예가 될 것 같아서 아래와 같이 오버로딩 해봤다. (23번째줄에서 사용) (생성자 만들기 귀찮아...)

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
#include <cstdio>
using namespace std;
struct point{
    int x,y;
 
};
point operator-(point p1){
    point ret;
    ret.x = -p1.x;
    ret.y = -p1.y;
    return ret;
}
point operator-(point p1,point p2){
    point ret;
    ret.x = p1.x - p2.x;
    ret.y = p1.y - p2.y;
    return ret;
}
int main() {
    point p1, p2;
    p1.x = 10, p1.y = 20;
    p2.x = 5, p2.y = 5;
    point p_one = -p1, p_two = p1-p2 ;
    printf("%d %d\n%d %d",p_one.x, p_one.y,p_two.x, p_two.y);
    return 0;
}
cs

output

- 10 - 20

5 15


컴파일 및 아웃풋


위의 23번째 줄은 다음과 동치이다. operator-를 일반 함수명이라고 생각한다면 더 이해하기 쉬울 것이다.

1
point p_one = operator-(p1), p_two = operator-(p1,p2);
cs



구조체나 클래스의 연산자 오버로딩전역 함수의 오버로딩


 일반적으로 전역 함수의 오버로딩은 단항 연산자의 경우 인자를 하나, 이항 연산자의 경우 인자를 두개 받는다. 이런 형태를 띄는게 전역 함수의 오버로딩인데 그 대표적인 예가 바로 위에서 보여준 예이다. 그렇다면 구조체나 클래스 안에서 구현한 연산자 오버로딩은 어떻게 다를까? 


  구조체나 클래스 안에서의 연산자 오버로딩의 경우 첫 번째 인자가 구조체나 클래스 인스턴스를 가르킨다고 생각하면 쉽다. 예제로 이해해 보자.

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
#include <iostream>
#include <cstdio>
struct point{
    int x,y;
     point operator-(){
        point ret;
        ret.x = -x;
        ret.y = -y;
        return ret;
    }
    point operator-(point p2){
        point ret;
        ret.x = x - p2.x;
        ret.y = y - p2.y;
        return ret;
    }
};
 
int main() {
    point p1, p2;
    p1.x = 10, p1.y = 20;
    p2.x = 5, p2.y = 5;
    point p_one = -p1, p_two = p1-p2 ;
    printf("%d %d\n%d %d",p_one.x, p_one.y,p_two.x, p_two.y);
    return 0;
}
cs

output

- 10 - 20

5 15


 연산자 오버로딩이 아까와는 달리 단항 연산자의 경우는 아무런 인자를 받지 않고, 이항 연산자의 경우 인자로 받는 항의 개수가 하나가 된다. 위에서 설명했다시피 자기 자신을 첫번째 인자라고 생각하면서 동작하게 되기 때문에 단항 연산자의 항은 자기자신으로 이미 한개가 정해져 있고, 이항 연산자의 경우는 첫번째 항으로 자기 자신이, 두번째 항으로 p2가 오게된 것이다. 
 23번째 줄을 아래의 문장으로 대치해도 같은 방식으로 동작하게 된다.(의미가 같다)
1
point p_one = p1.operator-(), p_two = p1.operator-(p2);
cs


더보기

 구조체나 클래스에 종속적인 배열 인덱스 연산자 오버로딩과 대입 연산자 오버로딩

 이 부분은 현재 시점에서 다루기 적절치 않은 부분이므로 개인적으로 공부하도록 합시다 ^ㅇ^

 메모리 관리나 레퍼런스 같은 복잡한 것들이 얽혀 있습니다. 실제로 C++의 라이브러리를 구현한다던가 하는 큰 규모의 프로젝트에서 사용될 법한 내용들은 처음 하시는 분들을 위해서 생략하도록 하겠습니다. 이런게 있구나 하고 넘어가시기 바랍니다. 



+ Recent posts