본문 바로가기

Language/C++

연산자 오버로딩(멤버함수)

연산자 오버로딩
class라는 사용자 정의 자료형을 가지고 =,+,-,*,/ 등의 연산을 하기 위함이다! 젠장 먼말인고 하니...
int a = 10;
int b = 10;
두개의 변수가 있다. 이를 int c; c = a + b; 를 하게 되면 전혀 틀린 문장(라인이 틀리다고 생각하자ㅡ,.ㅡ)이
아니다.
하지만...만약 이것이 기본 자료형이 아니라 클래스의 객체라면(참고로 클래스도 일종의 사용자 자료형이다^^)
A라는 클래스가 있다고 가정
A a1(10);
A a2(20);
A a3(a1+a2);

별다른 작업 없이 이게 된다고 생각하면 개오산 이다.(오산이 지명이더군..ㅋㅋ)

정의 :객체간의 연산을 허용하기 위함이 연산자 오버로딩 이다.

연산자 오버로딩도 함수의 일종이다. 이를 잊지 말아야 하며, C나C++ 등의 언어에서 정수형 타입은 int 와 같이
하나의 약속처럼 사용되는것을 잊지말자.

"operator"
연산자 오버로딩을 할때 반드시 붙여야 하는 키워드이다. 이 operator 바로 뒤에 '연!산!자!' 가 붙게 되는데
operator+
와 같은 형태이다. 그리고 함수처럼 괄호() 가 바로 들어간다. 이전체가 함수 이름이다^^

<형태>
classname operator+(const classname& p);

이 형태는 멤버 함수로 연산자 오버로딩을 했을때의 형태이다. 이 말은 일반적인 전역함수로도 연산자 오버로딩을 할수
있다는 것이다.^^

여기서 주목할것은 리턴타입이 멤버가 속한 해당 클래스 이름이며, 매개변수도 해당 클래스 이름의 인스턴스를 레퍼런스로 참조
하고 있다는 것이다. 단, 값을 참조는 하지만 조작을 하지 않겠다는 의미에서 const가 매개변수의 맨 앞에 붙어있다.

이런식으로 선언된 연산자 오버로딩 함수는 p3 = p1 + p2의 연산을 가능케 한다는 것이다. 저 함수의 일반적인 몸체부분을 간단하게 적으면
(A라는 클래스가 있다고 가정하고 A 안에는 private 영역에 int x 와 y가 있다고 가정하자.)
A operator+(const A& p)
{
    A temp(x = p.x, y = p.y);
    return A;
}

이런식으로 바디 부분이 정의가 되어있다. 여기서 두개의 의문이 생긴다. "단지 p1 + p2 를 했는데 저 함수가 호출이 되는게 어이없군 이론상
p1.operator+(p2); 가 맞지 않소~" 당신 대단하군......ㅋㅋㅋㅋㅋ 난 몰랐다..ㅋㅋㅋ 별로 신경을 않써서...ㅋㅋㅋ
이는 위에서 말한 !약속! 이라는 단어가 왜 나왔는지를 뒷받침 하는 첫 번째 이유이다. operator+() 는 + 만으로도 호출이 가능하게 약속이 되어있고
객체 끼리 + 를 하게 되면 묵시적으로 operator+ 함수를 호출하게 된다. 그래서 이름이 연산자 라는 이름이 들어간다.!
그런데 p1객체도 operator+() 를 가지고 있을것이고 p2도 operator+()를 가지는데 어디에 있는게 호출이 된다는 것일까?
이것이 바로 !약속! 이라는 것을 뒷받침해 주는 두 번째 요소이다. 만약 '멤버' 함수 연산자 오버로딩을 사용할 경우(반드시 멤버 확인하자)
좌측에 있는 객체의 operator+() 함수를 호출하고, 우측의 객체를 매개변수로 넘기자고 !약!속! 한것이다.
p1 + p2 ==> p1.operator+(p2);  이런식으로 묵시적으로 변형되게 된다. 그리고 리턴값이 역시 동일한 클래스(사용자 자료형) 를 갖기 때문에
객체끼리 계산한 값을 다른객체에 대입할수 있다는 것이며.....!!!!! 이때 복사 생성자가 호출이 이루어진다.

아래는 예제소스이다~^^
#include <iostream.h>

class Point
{
private:
    int x, y;
public:
    Point(int _x = 0,int _y = 0):x(_x), y(_y)//멤버 이니셜라이져.
    {
    }
    void ShowPosition();
    Point operator+(const Point& p);
};

void Point::ShowPosition()
{
    cout<<x<<""<<y<<endl;
}
Point Point::operator+(const Point& p)
{
    Point temp(x+p.x, y+p.y);//temp 객체를 생성하면서 p1의 x값과 p2dml x 값을 더하고 y값도 마찬가지로 더한후 그 값을 리턴.
    return temp;
}

int main()
{
    Point p1(1,2);
    Point p2(2,1);
    Point p3 = p1 + p2;//복사 생성자가 호출이 된다. p1+p2 는 결국 temp 라는 point 객체이다.

    p3.ShowPosition();

    return 0;
}