본문 바로가기
C++

단항 연산자의 오버로딩

by 상레알 2009. 2. 9.

이항 연산자 오버로딩과 단항 연산자 오버로딩의 가장 큰 차이점은 전달 인자의 개수에 있다.
이항 연산자 오버로딩을한 전역함수와 멤버 함수의 매개 변수 개수는 각각 2개, 1개 였다.
단형 연산자를 오버로딩할 때, 매개 변수의 개수는 이보다 1개 적다.(피연산자가의 개수가 이항연산자 보다 1개 적다)

Point& Point::operator++()
{
 x++;
 y++;
 return *this;
}

위 예제를 보면   "*this" 를 리턴하고 있다. "*this"가 의미하는 바는 무엇인가?


답: this는 객체 자신을 가리키는 포인터다. 여기에 "*연산을 하게되면 포인터가 가리키는 대상을 참조하겠다는 뜻이 된다. 즉 자기 자신을 리턴 하겠다는 의미를 지닌다.

x++과 y++ 연산으로 값 증가로 충분한거 아닌가? 자기 자신을 리턴하는 이유는 무엇인가?


답: 만약에 아무것도 리턴하지 않는다면  ++(++p); 이라든가   (++p).showposition();    같은 경우는 ++p 연산후에 아무것도 존재하지 않으므로 그 다음 연산은 불가능 하게 된다.

리턴 타입이 Point 가 아니라 Point& 인 이유는 어디에 있는가?


++(++p)  와 같은게 잇으면 p 값이 어떻게 되겟는가  2가 증가하게 된다. 예를 들어서  
int a=10;
++(++a);    //2증가
cout<<a<<endl;   // 12출력

이렇게 되면 주석과 같이 2가 증가되어 12가 출력이 되야되지만 Point 라고 한다면 값은 1만 증가된다. 왜냐하면 ++p 연산에 의해서 리턴되는 것은 p의 참조가 아닌, p의 복사본이기 떄문이다.


선연산과 후 연산의 구분

++ 연산자 특성상 두가지 형태로 함수를 오버로딩 해야만 한다. 피연산자의 위치에 따라서 의미가 달라지기 때문이다. 그런대 ++p와  p++은 동일하게 해석된다.    연산자의 이름도 같고, 피연산자의 개수도 같기 때문에 문제가 생긴다.!!

++p  -> p.operator++();
p++  ->  p.operator++();

++연산의 경우, 전위 증가(++p의 형태)와 후위 증가(p+)의 형태를 구분 짓기 어려우므로, 후위증가를 위한. 함수를 오버로딩할 경우 키워드 int를 매개 변수로 선언을 해라! 그러면 그것은 후위 증가를 의미하는것이다.

++p       ->  p.operator++();
p++       -> p.operator++(int);


(p++)++    <--  이거 안됨 ㅠ.ㅠ

왜냐하면 
후위증가 예 )

Point Point::operator++(int)
{
Point temp(x,y);     // Point temp(*this);
x++;
y++;                         // ++(*this);
return temp;
}
원래값을 변하지 않게 하기위해 temp 객체를 생성한다...
주석달린것으로 구현하는것이 좋다.이는 복사 생성자를 호출하는 형태로 객체를 복사하는  것이다.
그리고 마지막줄에 return  부분은 주의할 것이 잇는대 이 객체는 지역적으로 선언되어 있는 지역 객체라는것이다.  따라서 레퍼런스 형태로 리턴하면 안된다.(함수 호출이 끝나고 나면 객체는 소멸되니까!!!!)
 
교환 법칙

p+10  ==  10+p;


p+10    = >   p.operator+(10)
10+p   =>   10.operator+(p)  ?????

+는 교환 법칙이 성립하는대 이것을 멤버 함수에 의한 형태로 해석해 보면 엉터리 해석이 된다.
결국 전역 함수에 의한 연산자 오버로딩만이 이문제를 해결할 수 있다는 결론이 나온다.
전역함수로 오버로딩되었다면  operator+(10,p)   과 같이 해석이 될것이다.\

문제의 해결은 10+p 가 p +10이 되도록 바꿔주기만 하면 되는것이다-
해결방법은 의외로 간단하다.

Point operator+(int val, Point& p)
{
 return p+val;    // 단순히 피연산자의 위치만 변경
}

[ 참고 ]- 두 가지 형태(멤버 함수, 전역함수)로 동시에 오버로딩되는 것이 불가능하다. 그래서 + 연산자가 두 가지 형태로 오버로딩된 것이 이상하게 느껴질 수도 있으나.. 지금은 상황이 다르다. 오버로딩된 함수를호출하는 피연산자의 형태가 각각 다르기 떄문에 문제 되지 않는다. 그러나 오버로딩된 함수를 호출하는 피연산자의 형태가 같다면 문제가 된다.

임시 객체를 생성시 컴파일러에 따라서 프로그램 최적화가 진행 된다는 사실(속도가 빨라지고 메모리를 효율적으로 사용하게 된다.) 그러나 이는 컴파일러에 종속적인 사항이므로 자세한 언급을 하지 않겟다. 하지만 임시 객체를 사용하는 것이 경우에 다라서 보다 효율적이다=