C++ Chapter 9.6 : 증감 연산자 오버로딩
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
chapter 9. 연산자 오버로딩 : 증감 연산자 오버로딩
증감 연산자 :
++
,--
추가적인 설명은 이전 포스트인 9.1 연산자 오버로딩 시작하기 참고하기
증감 연산자는 전위
, 후위
를 구분해야 한다.
🔔 ‘전위’ 증감 연산자 오버로딩
int a = 2;
cout << ++a << endl; // 3 출력
- 이처럼 전위 증감 연산자는 값이 1만큼 증감하는게 바로 반영이 되야한다.
따라서 전위 증감연산자는 자기 자신을 참조로 리턴 해야한다.
전역 함수로 구현하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
friend ostream & operator << (ostream &out, const Digit &d) // 전역 함수
{
out << d.m_digit;
return out;
}
friend Digit & operator ++ (Digit & digit) // ⭐전역 함수
{
++digit.m_digit;
return digit;
}
};
int main()
{
Digit d(5);
cout << ++d << endl; // 6 출력
cout << d << endl; // 6 출력
return 0;
}
- 증감 연산자는 피연산자를 1개 필요로 한다.
- 전역 함수로 구현하니 인수 1개를 받아야 한다.
- 인수 👉 Digit 타입의 객체의 참조를 받는다
- 증가 시켜주어야 하니 const는 붙이지 않아야 한다.
- 인수로 넘겨 준 그 해당 객체의 멤버 값을 변경시킬거라 참조로 받아야 한다.
- 리턴 타입 👉 Digit 타입의 객체의 참조를 리턴한다.
- 인수로 받은 Digit 그 객체 그대로를 다시 내보낸다.
멤버 함수로 구현하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
friend ostream & operator << (ostream &out, const Digit &d) // 전역 함수
{
out << d.m_digit;
return out;
}
Digit & operator ++ () // ⭐멤버 함수
{
++m_digit;
return *this;
}
};
int main()
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
return 0;
}
- 증감 연산자는 피연산자를 1개 필요로 한다.
- 멤버 함수로 구현하니 인수는 필요 없다.
- 자기 자신(Digit타입 객체)이 곧 피연산자다.
- 리턴 타입 👉 Digit 타입의 객체의 참조를 리턴한다.
- 자기 자신(Digit타입 객체)을 리턴해야 하니
*this
을 리턴해준다.
- 자기 자신(Digit타입 객체)을 리턴해야 하니
🔔 ‘후위’ 증감 연산자 오버로딩
int a = 2;
cout << a++ << endl; // 2 출력
cout << a << endl; // 3 출력
- 이처럼 후위 증감 연산자는 값이 1만큼 증감하는게 세미 콜론을 만난 후에 반영된다.
후위 증감연산자의 구현
friend Digit operator ++ (Digit & digit, int) // 전역 함수 구현시
{
Digit temp(digit.m_digit);
++digit;
return temp;
}
Digit operator ++ (int) // 멤버 함수 구현시
{
Digit temp(m_digit);
++(*this);
return temp;
}
- 전위 증감 연산자와 구분하기 위해 dummy 매개변수인 int를 둔다.
- 전위 증감 연산자는 리턴 타입이 참조기 때문에 이 점에서 후위 연산자와 구분이 되기는 하지만 함수의 오버로딩에서 리턴 타입은 구분 기준이 되지 않는다. 참고 포스트
- 따라서 아무 역할도 하지 않는(dummy), 그저 전위 증감 연산자와 구분하는데 도움이 되기 위한
int
를 매개변수 자리에 둔다.
- 후위 증감 연산자는 연산의 결과가 바로 반영되지 않기 때문에 미리 연산 전의 값을 옮겨놓은 다음에 연산을 한다. 그리고 임시 저장해 둔 연산 전의 값을 리턴해준다.
- 증가 시킬 때 '전위' 증감 연산자를 필요로 하기 때문에 후위 연산자 오버로딩만 하지 말고 전위 연산자 오버로딩도 같이 해놓자.
- 전위 증감 연산자와 다르게 자기 자신을 참조로 리턴 하면 안되고 일반적인 call by value 타입으로 리턴 해야한다.
- 증가시키기 전의 값을 미리 옮겨 두었던 그 임시 객체를 리턴해야 하기 때문에
전역 함수로 구현하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
friend ostream & operator << (ostream &out, const Digit &d) // 전역 함수
{
out << d.m_digit;
return out;
}
//prefix
friend Digit & operator ++ (Digit & digit) // ⭐전역 함수
{
++digit.m_digit;
return digit;
}
//postfix
friend Digit operator ++ (Digit & digit, int) // ⭐전역 함수
{
Digit temp(digit.m_digit);
++digit;
return temp;
}
};
int main()
{
Digit d(5);
cout << d++ << endl; // 5 출력
cout << d << endl; // 6 출력
return 0;
}
- 증감 연산자는 피연산자를 1개 필요로 한다.
- 전역 함수로 구현하니 인수 1개를 받아야 한다.
- 사실
전위
증감 연산자와의 구분(오버로딩)을 위하여 dummy변수인 int가 하나 붙어있긴 하지만 인수는 1개만 받는다.
- 인수 👉 Digit 타입의 객체의 참조를 받는다
- 증가 시켜주어야 하니 const는 붙이지 않아야 한다.
- 인수로 넘겨 준 그 해당 객체의 멤버 값을 변경시킬거라 참조로 받아야 한다.
- 구현
- Digit
temp
(digit.m_digit);- 인수로 넘겨받은 digit 객체를 Digit 타입의 임시 객체 temp를 생성하여 이곳에 옮겨 놓는다.
- ++digit;
- 실제로 digit 객체를 증가 연산 시킨다.
- 이때 오버로딩된 전위 증감 연산자가 호출된다.
- return temp
- 미리 옮겨 놓았었던 증가시키기 전의 digit 객체인 임시 객체 temp를 리턴한다.
- Digit
- 리턴 타입 👉 Digit 타입의 객체를 call by value로 리턴한다.
- 증가시키기 전의 digit 객체의 정보를 복사해 저장해두었던 임시 객체 temp를 리턴한다.
- Digit& 참조로 리턴하면 안된다
- 임시 객체를 리턴할텐데 temp임시 객체는 지역변수라 함수가 끝나지면 사라지기 때문이다. 사라진 공간을 참조하게 되는 것이나 마찬가지이다.
- 그냥 temp임시 객체를 call by value로 리턴하면 임시 공간에 이 temp 객체가 복사되고 그 임시 공간이 R-value로서 리턴되는 식이라 문제가 없다.
- 참고 포스트
멤버 함수로 구현하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
friend ostream & operator << (ostream &out, const Digit &d)
{
out << d.m_digit;
return out;
}
//prefix
Digit & operator ++ ()
{
++m_digit;
return *this;
}
//postfix
Digit operator ++ (int)
{
Digit temp(m_digit);
++(*this);
return temp;
}
};
int main()
{
Digit d(5);
cout << d++ << endl; // 5 출력
cout << d << endl; // 6 출력
return 0;
}
- 증감 연산자는 피연산자를 1개 필요로 한다.
- 멤버 함수로 구현하니 인수는 필요 없다.
- 자기 자신(Digit타입 객체)이 곧 피연산자다.
- 사실
전위
증감 연산자와의 구분(오버로딩)을 위하여 dummy변수인 int가 하나 붙어있긴 하지만 인수는 받지 않는다.
- 사실
- 구현
- Digit
temp
(m_digit);- 자기 자신의 멤버값과 똑같은 멤버를 가진 Digit 타입의 임시 객체 temp를 생성한다.
- 증가 전 자신의 정보를 미리 다른 곳에 옮겨 놓은 것이나 마찬가지.
- ++(this);*
- 자기 자신을 증가 연산 시킨다.
- 이때 오버로딩된 전위 증감 연산자가 호출된다.
- return temp
- 미리 옮겨 놓았었던 증가시키기 전의 자기 자신을 복사해 둔 임시 객체 temp를 리턴한다.
- Digit
- 리턴 타입 👉 Digit 타입의 객체를 call by value로 리턴한다.
- 증가시키기 전의 자기 자신의 정보를 복사해 저장해두었던 임시 객체 temp를 리턴한다.
- Digit& 참조로 리턴하면 안된다
- 임시 객체를 리턴할텐데 temp임시 객체는 지역변수라 함수가 끝나지면 사라지기 때문이다. 사라진 공간을 참조하게 되는 것이나 마찬가지이다.
- 그냥 temp임시 객체를 call by value로 리턴하면 임시 공간에 이 temp 객체가 복사되고 그 임시 공간이 R-value로서 리턴되는 식이라 문제가 없다.
- 참고 포스트
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기