13.8 Overloading the increment and decrement operators

주홍영·2022년 3월 18일
0

Learncpp.com

목록 보기
151/199

https://www.learncpp.com/cpp-tutorial/overloading-the-increment-and-decrement-operators/

우리는 증감 연산자에 대해서 알고 있다
그리고 증감 연산자에는 두가지 버젼이 존재한다
prefix increment and decrement (e.g. ++x, --y)
postfix increment and decrement (e.g. x++, y--)

그리고 increment와 decrement 연산자 모두 단항연산자이고 operand를 modify하므로
member function으로 구현한다

먼저 prefix의 경우부터 살펴보자

Overloading prefix increment and decrement

prefix의 경우 unary operator overloading과 똑같이 구현된다

#include <iostream>

class Digit
{
private:
    int m_digit;
public:
    Digit(int digit=0)
        : m_digit{digit}
    {
    }

    Digit& operator++();
    Digit& operator--();

    friend std::ostream& operator<< (std::ostream& out, const Digit& d);
};

Digit& Digit::operator++()
{
    // If our number is already at 9, wrap around to 0
    if (m_digit == 9)
        m_digit = 0;
    // otherwise just increment to next number
    else
        ++m_digit;

    return *this;
}

Digit& Digit::operator--()
{
    // If our number is already at 0, wrap around to 9
    if (m_digit == 0)
        m_digit = 9;
    // otherwise just decrement to next number
    else
        --m_digit;

    return *this;
}

std::ostream& operator<< (std::ostream& out, const Digit& d)
{
	out << d.m_digit;
	return out;
}

int main()
{
    Digit digit(8);

    std::cout << digit;
    std::cout << ++digit;
    std::cout << ++digit;
    std::cout << --digit;
    std::cout << --digit;

    return 0;
}

위 코드의 출력은 다음과 같다

89098

Overloading postfix increment and decrement

The C++ language specification has a special case that provides the answer: the compiler looks to see if the overloaded operator has an int parameter. If the overloaded operator has an int parameter, the operator is a postfix overload. If the overloaded operator has no parameter, the operator is a prefix overload.

파라미터로 int를 받는다고 선언을 해놓으면 unary operator에 경우 postfix로 간주한다

class Digit
{
private:
    int m_digit;
public:
    Digit(int digit=0)
        : m_digit{digit}
    {
    }

    Digit& operator++(); // prefix has no parameter
    Digit& operator--(); // prefix has no parameter

    Digit operator++(int); // postfix has an int parameter
    Digit operator--(int); // postfix has an int parameter

    friend std::ostream& operator<< (std::ostream& out, const Digit& d);
};

// No parameter means this is prefix operator++
Digit& Digit::operator++()
{
    // If our number is already at 9, wrap around to 0
    if (m_digit == 9)
        m_digit = 0;
    // otherwise just increment to next number
    else
        ++m_digit;

    return *this;
}

// No parameter means this is prefix operator--
Digit& Digit::operator--()
{
    // If our number is already at 0, wrap around to 9
    if (m_digit == 0)
        m_digit = 9;
    // otherwise just decrement to next number
    else
        --m_digit;

    return *this;
}

// int parameter means this is postfix operator++
Digit Digit::operator++(int)
{
    // Create a temporary variable with our current digit
    Digit temp{*this};

    // Use prefix operator to increment this digit
    ++(*this); // apply operator

    // return temporary result
    return temp; // return saved state
}

// int parameter means this is postfix operator--
Digit Digit::operator--(int)
{
    // Create a temporary variable with our current digit
    Digit temp{*this};

    // Use prefix operator to decrement this digit
    --(*this); // apply operator

    // return temporary result
    return temp; // return saved state
}

std::ostream& operator<< (std::ostream& out, const Digit& d)
{
	out << d.m_digit;
	return out;
}

int main()
{
    Digit digit(5);

    std::cout << digit;
    std::cout << ++digit; // calls Digit::operator++();
    std::cout << digit++; // calls Digit::operator++(int);
    std::cout << digit;
    std::cout << --digit; // calls Digit::operator--();
    std::cout << digit--; // calls Digit::operator--(int);
    std::cout << digit;

    return 0;
}

코드를 보면 사전에 정의된 단항 연산자를 이용해
postfix 를 정의하고 있다
그리고 parameter에 int를 넣어 놓은 것을 확인할 수 있다

그리고 기존에 우리가 postfix와 prefix operator의 큰 차이점인
연산의 타이밍 또한 우리가 사용하던 대로 똑같이 작동한다
따라서 출력은 다음과 같다

5667665

여기서 두 함수의 정의를 똑같이 해주면 우리가 의도한 prefix postfix의 차이가 나타나지 않는다
따라서 코드를 보면 postfix의 경우 temp object를 만들어 temp를 return하는 것을 알 수 있다
따라서 prefix보다 postfix가 비효율적인 것을 알 수 있다
다만 우리가 의도한 출력이 나오게 된다

만약 두 operator 모두 구현을 똑같이 해놓으면 출력은 다음과 같다

5677655

따라서 의도한 postfix와 prefix의 작동방식을 구현하기 위해서는 정의할 때 다르게 해줘야 한다

참고로 괄호를 붙인다고 하더라도 postfix가 완료되고 return 하는 것은 아니다
예시:

	int i = 3;
    int b = i++;
    int c = (i++);
    std::cout << b << c << i << std::endl;

c의 경우 postfix에 괄호를 쳐서 증가 연산을 다하고 c에 집어 넣을것 같지만
그렇지 않고 i를 먼저 return 한다
operator overloading을 보면 temp를 반환하기 때문에 괄호를 치더라도 return값은 temp로
정해져 있어서 괄호가 없는거랑 똑같은 결과가 나온다
헷갈릴 수 잇으니 잘 기억해두자

따라서 출력은

345

따라서 괄호가 없는 아래 버전도

	int i = 3;
    int b = i++;
    int c = i++;
    std::cout << b << c << i << std::endl;

똑같은 출력

345

를 보여준다

profile
청룡동거주민

0개의 댓글