Notice
Recent Posts
Recent Comments
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

SYDev

C++ Chapter 10-1 : 연산자 오버로딩의 이해와 유형 본문

Programming Lang/C++

C++ Chapter 10-1 : 연산자 오버로딩의 이해와 유형

시데브 2023. 7. 23. 15:40

연산자 오버로딩

#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)   //operator+라는 이름의 함수
    {
        Point pos(xpos+ref.xpos, ypos+ref.ypos);
        return pos;
    }
};

int main(void)
{
    Point pos1(3, 4);
    Point pos2(10, 20);
    Point pos3 = pos1+pos2; //pos1.operator+(pos2)으로 해석
    
    pos1.ShowPosition();
    pos2.ShowPosition();
    pos3.ShowPosition();

    return 0;
}
[3, 4]
[10, 20]
[13, 24]

 함수를 선언할 때 키워드 'operator' 뒤에 연산자를 붙이면 해당 함수를 호출할 때 연산자만으로 호출이 가능해진다. 위 예제를 예시로 들었을 때 pos1+pos2는 pos1.operator+(pos2)로 해석된다. 

 

 이는 멤버함수에 의한 연산자 오버로딩의 한 예시이고, 연산자 오버로딩 방법에는 멤버함수에 의한 방법전역함수에 의한 방법이 있다.

 

연산자를 오버로딩하는 두 가지 방법

  • 멤버함수에 의한 연산자 오버로딩 -> pos1+pos2가 pos1.operator+(pos2)로 해석됨
  • 전역함수에 의한 연산자 오버로딩 -> pos1+pos2가 operator+(pos1, pos2)로 해석됨
  • 동일한 자료형을 대상으로 +연산자를 전역함수, 멤버함수 기반으로 동시에 오버로딩 할 경우 -> 멤버함수 기반으로 오버로딩 된 함수가 우선시되어 호출(오래된 일부 컴파일러에서는 compile error)

 다음은 전역함수 기반 연산자 오버로딩 예시이다.

#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);	
    //operator+ 함수 내에서는 Point 클래스의 private 영역에 접근 가능, Point 클래스가 연산 +에 대해 연산자 오버로딩이 되었음을 의미
};

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(10, 20);
    Point pos3 = pos1+pos2; //operator+(pos1, pos2)으로 해석
    
    pos1.ShowPosition();
    pos2.ShowPosition();
    pos3.ShowPosition();

    return 0;
}
[3, 4]
[10, 20]
[13, 24]

 

오버로딩이 불가능한 연산자의 종류

  • . 멤버 접근 연산자
  • .* 멤버 포인터 연산자
  • :: 범위 지정 연산자
  • ?: 조건 연산자(3항 연산자)
  • sizeof 바이트 단위 크기 계산
  • typeid RTTI 관련 연산자
  • static_cast 형변환 연산자
  • dynamic_cast 형병환 연산자
  • const_cast 형병환 연산자
  • reinterpret_cast 형병환 연산자

멤버함수 기반으로만 오버로딩이 가능한 연산자

  • = 대입 연산자
  • () 함수 호출 연산자
  • [] 배열 접근 연산자(인덱스 연산자)
  • -> 멤버 접근을 위한 포인터 연산자

 

연산자 오버로딩 주의사항

  • 본래의 의도를 벗어난 형태의 연산자 오버로딩은 좋지 않다. (새로운 객체를 생성하는 것이 아닌 본래 객체의 값을 증가시키는 방향은 좋지 않다.)
  • 연산자의 우선순위와 결합성은 바뀌지 않는다. (*,/,%,+,-, ....)
  • 매개변수의 디폴트 값 설정이 불가능하다. 
  • 연산자의 순수 기능까지 빼앗을 수 없다. (+연산자 오버로딩을 +기능이 아닌 *기능으로 정의할 수 없다.)

 

연산자 오버로딩이라 불리는 이유?

int num = 3 + 4;
Point pos3 = pos1 + pos2	//pos1과 pos2는 Point형 객체

 함수가 오버로딩되면 전달되는 인자에 따라서 호출되는 함수가 달라지듯이, 위와 같이 연산자가 오버로딩 되면 피연산자의 종류에 따라 연산 방식이 달라지기 때문에 연산자 오버로딩이라 불린다.


출처 : 윤성우, <윤성우의 열혈 C++ 프로그래밍>, 오렌지미디어, 2010.05.12