728x90
반응형
수업시간에 블로그로 필기한거 팀블로그에도 같이 올림
===============================================================================================
위의 소스를 모르는 사람은 없을 것이다.
하지만 다음과 같은 소스가 가능할까?
객체를 객체끼리 더해서 대입한다...라는 뜻인거 같은데 가능해보이지는 않는다.
물론 가능하지 않다.
하지만 C++에서는 가능하도록 만들 수 있다.
바로 연산자 오버로딩을 이용해서 연산자를 재정의하면 위의 코드가 가능해지도록 만들 수 있다.
더하기 연산자를 다시 한번 자세히 살펴보도록 하자.
a = 1 + 2;
라는 코드가 있다고 한다면, 이 코드를 자세히 보면 연산자 우선 순위에 의해서 +가 먼저 실행되고, =가 그 뒤에 실행되는데, + 를 보면 + 를 기준으로 앞 뒤의 정수들 더해서 정수를 만들어 준다는 것을 알 수 있다.
이를 바꿔 말하면, 두 개의 정수형 인자를 받아서 한개의 정수를 리턴해준다고도 표현할 수 있을 것이다. 마치 함수와 같이 말이다.
이것을 함수로 나타낸다면 int 더하기(int, int) 이런식으로 표현할 수 있을 것이다.
C++에서는 함수를 오버로딩(재정의)할 수 있는데 마찬가지로 연산자 또한 재정의를 할 수 있다. 따라서 이 + 를 재정의해서 객체와 객체를 어떤 조건으로 더하고 다시 객체를 리턴해주는 식으로 만들어 준다면 객체끼리의 덧셈도 가능하게 만들 수 있을 것이다.
다만, 연산자를 재정의할 때는 함수와 구별하기 위해 operator라는 예약어를 사용한다.
사용법은 다음과 같다.
실제로 사용한 소스는 아래와 같다.
operator+를 구현한 부분을 보면 인자를 하나로 받아서 자신의 데이터와 더하고 자신을 다시 리턴해주는 것을 볼 수 있다.
즉, test = test + obj 에서 test에 obj를 더해서 test를 다시 리턴해주는 것이다.
물론 클래스 밖에서 전역함수로 선언하여 구현을 할 수도 있지만(만약 이렇게 한다면 연산자 앞뒤의 객체 두개를 인자로 받아야할 것이다.) 이렇게 한다면, 다른 사람에 의해서 전역함수를 오버로딩하여 클래스의 private멤버들의 값을 수정하는 보안상의 취약점이 생길 수 있기 때문에 클래스의 안에서 구현하는 것이 좋다.
그런데 위의 소스에는 한가지 맹점이 있다.
만약 다음과 같은 코드가 있다고 하자.
위의 코드는 보기에는 아무런 문제가 없어보인다.
하지만 만약 클래스 내에서 동적할당을 하는 부분이 있다고 한다면 심각한 문제를 발생 시킬 수 있다.
클래스의 멤버중 포인터가 동적할당을 받아 가르키고 있다면, 만약 위의 코드로 자신을 대입하게 되면 동적할당을 다시 받아 포인터가 새로 할당받은 메모리를 가르키게 될 것이고, 기존의 할당받은 메모리는 포인터를 잃어버리게 된다.
이것을 계속해서 반복하게 된다면 delete 시켜줄 수 없는 잃어버린 메모리들이 늘어나게 되고 이것은 메모리 누수로 이어지게 되어 시스템에 악영항을 끼치게 된다.
따라서 아래와 같이 고쳐주어야한다.
===============================================================================================
int a;
a = 1 + 2;
a = 1 + 2;
위의 소스를 모르는 사람은 없을 것이다.
하지만 다음과 같은 소스가 가능할까?
MyClass obj1;
MyClass obj2;
obj1 = obj1 + obj2;
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;
obj = obj;
위의 코드는 보기에는 아무런 문제가 없어보인다.
하지만 만약 클래스 내에서 동적할당을 하는 부분이 있다고 한다면 심각한 문제를 발생 시킬 수 있다.
클래스의 멤버중 포인터가 동적할당을 받아 가르키고 있다면, 만약 위의 코드로 자신을 대입하게 되면 동적할당을 다시 받아 포인터가 새로 할당받은 메모리를 가르키게 될 것이고, 기존의 할당받은 메모리는 포인터를 잃어버리게 된다.
이것을 계속해서 반복하게 된다면 delete 시켜줄 수 없는 잃어버린 메모리들이 늘어나게 되고 이것은 메모리 누수로 이어지게 되어 시스템에 악영항을 끼치게 된다.
따라서 아래와 같이 고쳐주어야한다.
void operator=(MyClass &obj)
{
if(this == &obj)
{
return;
}
//객체끼리의 대입을 구현
}
{
if(this == &obj)
{
return;
}
//객체끼리의 대입을 구현
}
728x90
'기술자료 > C C++' 카테고리의 다른 글
[賢彬] _STDC_, _P() 의 의미. (1) | 2009.08.11 |
---|---|
[賢彬] C++ 에서 멤버 함수포인터 사용하기 (1) | 2009.08.10 |
const 에 대해서 알아봅시다.. (1) | 2009.08.07 |
[賢彬][c++]도대체 가상함수는 어디에다 쓰는 것일까?? (1) | 2009.08.07 |
[賢彬][C++] ofstream, ifstream에 대해서 (0) | 2009.08.05 |
[賢彬][C++] 인라인(inline) 함수 (1) | 2009.08.04 |
동적할당으로 스텍 만들기 (1) | 2009.08.03 |
extern "C" (2) | 2009.07.25 |