[문과 코린이의 IT 기록장] C,C++ - 연산자 오버로딩 2 : 단항 연산자 오버로딩(증감 연산자 오버로딩, 전위증가 및 후위증가의 구분)
[문과 코린이의 IT 기록장] C,C++ - 연산자 오버로딩 2 : 단항 연산자 오버로딩
(증감 연산자 오버로딩, 전위증가 및 후위증가의 구분)
1. 증감 연산자 오버로딩
++ pos; // pos는 객체
a. 맴버함수로 오버로딩하는 경우 : pos.operator++();
b. 전역함수로 오버로딩하는 경우 : operator++.(pos);
#include <iostream>
using namespace std;
class Point { // point 클래스
private:
int xpos, ypos;
public:
Point(int x = 0, int y = 0) : xpos(x), ypos(y){ } // 생성자 (x=0, y=0으로 초기화)
void ShowPosition() const { // [xpos, ypos] 출력 함수
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
Point& operator++() {
// 반환형이 참조형(point&)인, operator++함수
// ++연산자가 맴버함수의 형태로 오버로딩
xpos += 1;
ypos += 1;
return *this // 함수 체이닝 기법을 사용하기 위해 작성. 연산된 참조값(객체 그 자체의 값) 전달.
ex ) Point & ref = ++pos = pos.operator++()이다. 반환된 *this, 즉 객체 자신에 대한 정보(참조값)이 존재하고, 그 값을 반환한다(반환형이 참조형이기 때문). 이와 같이 객체의 참조값을 반환하는 함수의 형태가 존재해야, 체이닝기법이 가능하다.
}
friend Point& operator--(Point& ref); // Point & operator--함수는, Point 클래스의 맴버에 접근 가능하다.
};
Point& operator--(Point& ref) { // 인자로 전달된 pos객체를, 참조자 ref로 받는다.
ref.xpos -= 1;
ref.ypos -= 1;
return ref // 참조형(Point&이기 때문에)으로 반환한다.(복사본 x) (this포인터 사용은 맴버함수에서 사용)
}
int main() {
Point pos(1, 2);
++pos; // pos.operator++();
pos.ShowPosition();
--pos; // operator--.(pos)
pos.ShowPosition();
++(++pos); // ++(pos.operator++()) = ++(pos의 참조값) = (pos의 참조값).operator++();
pos.ShowPosition();
--(--pos); // --(operator--.(pos)) = --(pos의 참조값) = operator--.(pos의 참조값);
pos.ShowPosition();
return 0;
}
2. 전위증가 및 후위증가의 구분
[ C++에서의 전위연산 vs 후위연산 해석규칙 ] (1) ++ a. ++pos : pos.operator( ); b. pos++ : pos.operator++(int); (2) -- a. --pos : pos.operator--( ); b. pos-- : pos.operator--(int); |
cf ) int는 구분목적이지, 의미를 지니지는 않는다.
ex )
#include <iostream>
using namespace std;
class Point { // Point 클래스
private:
int xpos, ypos;
public:
Point(int x=0, int y=0): xpos(x), ypos(y){ } // 생성자
void ShowPosition() const { // xpos, ypos 출력 (const 맴버함수 : 호출한 객체의 맴버변수를 변경하지 못하는 함수)
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
Point& operator++() { // 전위증가, 반환형은 참조형.
xpos += 1;
ypos += 1;
return *this // 참조값(객체) 그 자체를 반환
}
const Point operator++(int) { // 후위증가
const Point retobj(xpos, ypos); // const Point retobj(*this); (복사생성자 구문과 같다) / 먼저 기존값을 복사해놓고, +1계산.
xpos += 1;
ypos += 1;
return retobj; // 기존값(참조값 = 객체 그 자체)을 반환함으로서, 후위증가 가능
}
friend Point& operator--(Point& ref);
friend const Point operator--(Point& ref, int);
};
Point& operator--(Point& ref) { // 전위감소
ref.xpos -= 1;
ref.ypos -= 1;
return ref;
}
const Point operator--(Point& ref, int) { // 후위감소
const Point retobj(ref); // const 객체라한다
ref.xpos -= 1;
ref.ypos -= 1;
return retobj;
}
int main() {
Point pos(3, 5);
Point cpy;
cpy = pos-- // pos.operator--(int);
cpy.ShowPosition(); // 후위증가는 ;를 만난 이후에 연산이 진행된다. 따라서 cpy는 연산이 진행되기 전의 값을 지닌다.
pos.ShowPosition(); // 위와 같은 원리로, pos는 연산 후의 값을 지니게 된다.
cpy = pos++; // pos.operator++(int);
cpy.ShowPosition();
pos.ShowPosition();
return 0;
}
* 유의사항 - 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다. - 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다. - 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :) |