Minwoo Dev.

[C++] 연산자 오버로딩이란, +-*/ 연산자 오버로딩 방식 본문

C++

[C++] 연산자 오버로딩이란, +-*/ 연산자 오버로딩 방식

itisminu 2024. 7. 19. 10:16
728x90
반응형
SMALL

코드를 작성하다 보면 우리가 가장 많이 사용하는 것 중 하나가 바로 "연산자" 일 것이다.

 

int a = b + c;

위처럼 연산자를 사용하여 우리는 다양한 값을 계산할 수 있다.

 

C++ 에서는 우리가 알고있는 사칙연산(+, -, *, /) 외에도 정말 많은 연산자가 존재하는데, 이러한 연산자를 우리의 의도에 맞게 변경하려고 하면 어떤 방법을 사용해야 할까?

 

간단히 예를 들어, x와 y값을 가지는 Point 클래스끼리 + 연산을 수행한다고 하자.

#include<iostream>
using namespace std;

class Point{ // 두 점을 나타내는 Point 클래스
private:
    int xpos, ypos;
public:
    Point(int x = 0, int y = 0):xpos(x),ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
};

int main(void){
    Point pos1(3, 4);
    Point pos2(2, 5);
    Point pos3 = pos1 + pos2; // 두 점의 덧셈결과를 pos3에 대입
    pos3.ShowPosition();
    return 0;
}

 

위와 같은 경우에서, 우리는 pos3에 pos1과 pos2의 연산 결과를 담고자 한다.

일반적인 덧셈처럼 연산이 수행될 거 같지만, 결과는 그렇지 않다.

 

컴퓨터는 pos1 안의 xpos와 ypos를 각각 나누어 계산하는 것을 인식하고 있지 않기때문에 기본적인 + 연산으로 수행하고자 할 것이다.

따라서 이러한 경우에, 우리가 연산자 오버로딩을 사용해야 하는 것이다.

 


연산자 오버로딩(Operator Overloading)

반환형 operator연산자(매개변수){
    함수 내용
}
  • 기본 연산자의 기능만으로는 계산을 하는 데 한계가 있을 때 오버로딩을 통해여 특정 객체끼리의 연산을 수행하도록 함
  • 기본 연산자의 기능에서 벗어나지 않는 범위에서 기능을 오버로딩
  • 코드를 작성하는 두 가지 방법이 존재
    • 멤버 함수로써의 오버로딩
    • 전역 함수로써의 오버로딩(friends 사용)

 

#include<iostream>
using namespace std;

class Point{
private:
    int xpos, ypos;
public:
    Point(int x = 0, int y = 0):xpos(x),ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
};

int main(void){
    Point pos1(3, 4);
    Point pos2(2, 5);
    Point pos3 = pos1 + pos2;
    pos3.ShowPosition();
    return 0;
}

 

위 코드를 연산자 오버로딩을 통해 수정하는 방식으로 설명하겠다.

우선, 위 코드에서 우리가 오버로딩해야할 연산자는 + 연산자이다.

 

멤버 함수로의 오버로딩

#include<iostream>
using namespace std;

class Point{
private:
    int xpos, ypos;
public:
    Point(int x = 0, int y = 0):xpos(x),ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    Point operator+(const Point &ref){ // 연산자 오버로딩
        Point pos(xpos + ref.xpos, ypos + ref.ypos);
        return pos;
    }
};

int main(void){
    Point pos1(3, 4);
    Point pos2(2, 5);
    Point pos3 = pos1 + pos2;
    pos3.ShowPosition();
    return 0;
}

 

연산자 오버로딩을 통해 사용할 클래스의 내부에 오버로딩 함수를 기입하는 방식이다.

오버로딩한 함수를 자세히 들여다보면,

Point operator+(const Point &ref){
        Point pos(xpos + ref.xpos, ypos + ref.ypos);
        return pos;
    }

 

operator+ 이라는 이름으로 함수가 정의되어 있다.

이 경우에는 두 점을 더하여 결과값을 반환해야 하므로 반환 형식도 Point인 함수가 되는 것이다.

pos1 + pos2;

 

연산자 오버로딩에서는, 위처럼 나온 식을 컴파일러가 계산 과정에서 아래와 같이 변형하여 연산을 수행한다.

pos1.operator+(pos2);

 

즉, pos1의 멤버함수인 operator+를 사용하여 게산하는데, 뒤에 있는 값은 매개변수로 전달되는 것이다.

 

따라서 위의 함수에서도 인자값으로 Point 의 참조형 값인 ref를 받아와서 연산을 수행한다.

 

함수 내부에서는 새로운 Point 객체에 멤버변수인 xpos, ypos와 인자로 받아온 ref.xpos, ref.ypos를 각각 더하는 계산을 수행하고, 이 새로운 Point 객체를 반환하게 된다.

 

 


 

전역 변수로의 오버로딩

  • 클래스 내부에 friend 선언으로 변수 접근 가능하도록 함
  • 클래스 외부에 선언되어 있으므로 pos1과 pos2 모두 매개변수로 받아와야 함
#include<iostream>
using namespace std;

class Point{
private:
    int xpos, ypos;
public:
    Point(int x = 0, int y = 0):xpos(x),ypos(y){}
    void ShowPosition() const{
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    friend Point operator+(const Point &pos1, const Point &pos2);
};

Point operator+(const Point &pos1, const Point &pos2){ // 전역 함수 오버로딩
    Point pos(pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos);
    return pos;
}

int main(void){
    Point pos1(3, 4);
    Point pos2(2, 5);
    Point pos3 = pos1 + pos2;
    pos3.ShowPosition();
    return 0;
}

 

전역 함수로의 오버로딩은 가장 바깥 인덴트에 함수를 작성해주면 된다.

 

그리고 클래스 외부에서는 멤버변수에 접근할 수 없기때문에 friend 선언을 Point 클래스 내부에 작성해줌으로 pos1과 pos2의 각 xpos, ypos에 접근할 수 있게된다.

 

pos1 + pos2;

 

전역 함수로 작성하면 위 코드가

operator+(pos1,pos2);

 

이렇게 변경되어 연산이 수행된다.

그래서  pos1과 pos2를 모두 매개변수로 받아와야 하는 것이다.

 

 

 


나머지 -, *, / 연산자도 위와 같은 방식으로 operator-, operator*, operator/ 와 같이 작성하고 내용을 수정한다면 쉽게 연산자 오버로딩을 할 수 있을 것이다.

 

728x90
반응형
LIST