증가/감소 연산자 오버로딩 |
따라서 ++(++p) 연산에서도 괄호 안의 연산인 p.operator++() 함수 호출이 끝나고 나서 이 자리에 p가 그대로 리턴이 돼야 이런 증가 연산이 제대로 이루어 질 수 있다.
멤버 함수 정의부를 보면 return 타입이 *this인 것을 알 수 있다. 여기서의 this는 Point 객체의 포인터를 의미하는데, *를 붙였으니까 Point객체 자신을 의미한다. 그럼 나 자신을 무엇으로 리턴 하느냐? 바로 Point& 즉, 참조로 리턴을 하는 것이다.
괄호 안은 p.operatr++()이 되고 이 연산이 끝나고 p의 참조를 리턴하는데 p의 참조는 p와 같다. ++(p참조) -> p참조 . operator++() 이 것이 된다. p참조는 p자신 이므로, p.operator++() 이 되는 것과 같다. 그래서 결과가 ' 3 4 '로 연산이 제대로 되는 것이다.
만약 참조로 리턴 안하고 Point로 리턴 한다면 어떻게 될까?
그냥 Point를 리턴 한다면, 나 자신을 복사 해서 리턴 하는것이다. 그래서 ++(++p) 에서 괄호 안의 연산후에 이 자리에 오는 것은 p가 아니라 p객체의 복사본이 리턴되는것이다. 그리고 p객체의 복사본을 가지고 ++연산을 하게 되는것이다. 결과적으로 리턴하는 순간에 새로운 객체를 만들어서 리턴하는 꼴이 되므로 p객체는 단지 한번만 증가 하게 되는 것이다. (이것이 문제가 된다)
선연산과 후연산의 구분 |
- ++ p : 변수의 값을 먼저 증가 시킨후 연산
- p++ : 연산후 값 증가
우리가 단항 연산자 오버로딩을 설계할 때, 이처럼 문법상 기본 자료형이 하는 일을 따라 간다면 우리는 선연산 후연산이 다르게 동작 되어야 하는것을 알 수 있는 것이다. 그래서 우리는 호출 되는 함수의 구분을 위해 C++은 또 하나의 약속을 해야 하는 것이다. 다음과 같이 말이다.
- ++p 은 p.operator ++( );
- p++ 은 p.operator ++(Data Type);
여기서 선언된 데이터 타입은(int, double 등등의...) ++ 연산을 구분 지어 주기 위해서만 의미를 가진다. 예제 소스를 보자.
결가 값을 보면 (p1++).ShowPosition(); 이 부분에 1 2 값을 출력하는 것을 알 수 있다. p1객체 뒤에 증가 연산자가 왔으므로, 이것은 후 증가 의미를 가지기 때문이다. 그후 p1을 출력해보면, 후 증가의 값을 눈으로 확인해볼 수 있는 것이다.
그럼 증가 하기 이전의 값을 얻기 위한 함수는 어떻게 만들까? 그 함수는 바로 이 부분이다.
증가하기 이전에 값을 만든 다음에 (temp) 그 다음에 값을 증가 시키고,
리턴 할때는 증가 하기 이전에 객체를 이전하면 된다. 이 함수의 경우에는 참조로 리턴이 안됐는데, 이 함수는
참조로 리턴 할 수 없다.
왜냐? 참조로 리턴(return) 할 수 없는것이 무엇인가? 바로 지역 변수, 지역객체 이다. 여기서 temp는
지역적으로 선언된것이므로 참조로 리턴 될 수 없다. 만약 리턴 된다고 해도 리턴 되고 나서 이 리턴값은 바로 사라지기 때문이다. 이게 바로 연산자 오버로딩의 한계점이라고 할 수 있다.
'Programming > C / C++' 카테고리의 다른 글
[C++] 쉬프트 연산자 오버로딩 (cout, cin, endl) (1) | 2010.09.19 |
---|---|
[C++] 연산자 오버로딩 - 교환법칙의 성립과 임시객체(Temporary Object) (0) | 2010.09.18 |
[C++] 연산자 오버로딩 (Operator Overloading)의 두가지 방법 (1) | 2010.09.18 |
[C++] 상속의 마지막, 다중 상속(Multiple Inheritance) (0) | 2010.09.17 |
가상 함수 동작 원리와 단점 (0) | 2010.09.17 |