LuvSea

C++ 연산자 오버로딩 본문

sTudy

C++ 연산자 오버로딩

사랑海 2009. 8. 10. 14:25
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

int a;

a = 1 + 2;

위의 소스를 모르는 사람은 없을 것이다.

하지만 다음과 같은 소스가 가능할까?

MyClass obj1;
MyClass obj2;

obj1 = obj1 + obj2;

객체를 객체끼리 더해서 대입한다...라는 뜻인거 같은데 가능해보이지는 않는다.


물론 가능하지 않다.

하지만 C++에서는 가능하도록 만들 수 있다.
바로 연산자 오버로딩을 이용해서 연산자를 재정의하면 위의 코드가 가능해지도록 만들 수 있다.


더하기 연산자를 다시 한번 자세히 살펴보도록 하자.

a = 1 + 2;
라는 코드가 있다고 한다면, 이 코드를 자세히 보면 연산자 우선 순위에 의해서 +가 먼저 실행되고, =가 그 뒤에 실행되는데, + 를 보면 + 를 기준으로 앞 뒤의 정수들 더해서 정수를 만들어 준다는 것을 알 수 있다.

이를 바꿔 말하면, 두 개의 정수형 인자를 받아서 한개의 정수를 리턴해준다고도 표현할 수 있을 것이다. 마치 함수와 같이 말이다.

이것을 함수로 나타낸다면 int 더하기(int, int) 이런식으로 표현할 수 있을 것이다.

C++에서는 함수를 오버로딩(재정의)할 수 있는데 마찬가지로 연산자 또한 재정의를 할 수 있다. 따라서 이 + 를 재정의해서 객체와 객체를 어떤 조건으로 더하고 다시 객체를 리턴해주는 식으로 만들어 준다면 객체끼리의 덧셈도 가능하게 만들 수 있을 것이다.

다만, 연산자를 재정의할 때는 함수와 구별하기 위해 operator라는 예약어를 사용한다.

사용법은 다음과 같다.

리턴값 operator연산자(인자)
{
    구현
}


실제로 사용한 소스는 아래와 같다.

#include <iostream.h>

class MyClass
{
  private:
    int val;

  public:
    void SetVal(int k)
    {
      val = k;
    }
    
    void PrintVal()
    {
      cout<<val<<endl;
    }

    MyClass & operator+(MyClass &obj)
    {
      val += obj.val;
      return *this;
    }
};

int main()
{
  MyClass obj;

  obj.SetVal(5);

  MyClass test;

  test = test + obj;

  test.PrintVal();

  return 0;
}

operator+를 구현한 부분을 보면 인자를 하나로 받아서 자신의 데이터와 더하고 자신을 다시 리턴해주는 것을 볼 수 있다.

즉, test = test + obj 에서 test에 obj를 더해서 test를 다시 리턴해주는 것이다.

물론 클래스 밖에서 전역함수로 선언하여 구현을 할 수도 있지만(만약 이렇게 한다면 연산자 앞뒤의 객체 두개를 인자로 받아야할 것이다.) 이렇게 한다면, 다른 사람에 의해서 전역함수를 오버로딩하여 클래스의 private멤버들의 값을 수정하는 보안상의 취약점이 생길 수 있기 때문에 클래스의 안에서 구현하는 것이 좋다.


그런데 위의 소스에는 한가지 맹점이 있다.

만약 다음과 같은 코드가 있다고 하자.

MyClass obj;

obj = obj;

위의 코드는 보기에는 아무런 문제가 없어보인다.
하지만 만약 클래스 내에서 동적할당을 하는 부분이 있다고 한다면 심각한 문제를 발생 시킬 수 있다.

클래스의 멤버중 포인터가 동적할당을 받아 가르키고 있다면, 만약 위의 코드로 자신을 대입하게 되면 동적할당을 다시 받아 포인터가 새로 할당받은 메모리를 가르키게 될 것이고, 기존의 할당받은 메모리는 포인터를 잃어버리게 된다.

이것을 계속해서 반복하게 된다면 delete 시켜줄 수 없는 잃어버린 메모리들이 늘어나게 되고 이것은 메모리 누수로 이어지게 되어 시스템에 악영항을 끼치게 된다.

따라서 아래와 같이 고쳐주어야한다.

void operator=(MyClass &obj)
{
    if(this == &obj)
    {
        return;
    }
    //객체끼리의 대입을 구현
}
Comments