오븐 노트

[C++] 연산자 오버로딩 #1 ~ 2 본문

Develop/C++

[C++] 연산자 오버로딩 #1 ~ 2

오 븐 2022. 10. 5. 17:50
#include <iostream>
using namespace std;

// 연산자 오버로딩(Operator Overloading)

// 연산자 vs 함수
// - 연산자는 피연산자의 개수/타입이 고정되어 있음.

// 연산자 오버로딩이란? 정해진 몇가지 타입 외에 자기자신의 클래스에 대한 특정 연산을 지원하고 싶을 때 사용하는 것
// 우선 연산자 함수 정의 필요
// 일반 함수가 멤버 함수, 전역 함수로 나누어지는것처럼 연산자 함수도 두가지로 나누어짐.

// ※-------------------------------------------------------------------------------------※
// - 멤버 연산자 함수 version
// -- a op b 형태에서 왼쪽 기준으로 실행됨 (a가 클래스여야 가능, a를 '기준 피연산자'라고 함)
// -- 한계) a가 클래스가 아니면 사용하지 못함.

// - 전역 연산자 함수 version
// -- a op b 형태라면 a, b 모두를 연산자 함수의 피연산자로 만들어준다.

// 둘 중 하나만 지원하는 경우도 있음.
// - 대표적으로 대입 연산자 (a = b)는 전역 연산자 version으로는 불가능하다.
// ※-------------------------------------------------------------------------------------※

// 복사 대입 연산자 => 대입 연산자 중, 자기 자신의 참조 타입을 인자로 받는 것
// - 비슷한 용어 [복사 생성자] [복사 생성자] [대입 연산자] [복사 대입 연산자]

// 기타
// - 모든 연산자를 다 오버로딩 할 수 있는 것은 아니다. ex) :: . .*
// - 모든 연산자가 다 2개 항이 있는 것은 아님. ex) ++ -- (단항 연산자가 대표적 예시)
// - 증감 연산자 ++ --
// -- 전위형 (++a) operator++()
// -- 후위형 (a++) operator++(int)

class Position
{
public:

    Position(const Position& arg) // 자기 자신의 참조 타입을 매개변수로 받는 생성자인 '복사 생성자'
    {

    }

    Position operator+(const Position& arg)
    {
        Position pos;
        pos._x = _x + arg._x;
        pos._y = _y + arg._y;
        return pos;
    }

    Position operator+(int arg)
    {
        Position pos;
        pos._x = _x + arg;
        pos._y = _y + arg;
        return pos;
    }

    bool operator==(const Position& arg)
    {
        return _x == arg._x && _y == arg._y;
    }

    Position& operator=(int arg) // 멤버 함수에서만 가능 // operator를 생성할때는 자기 자신의 참조값을 반환하도록 생성할때가 많다.
    {
        _x = arg;
        _y = arg;
        return *this; // this는 자기 자신의 주소를 담고있는 포인터 변수
    }
    
    // [복사 생성자] [복사 대입 연산자] 등이 특별 대우를 받는 이유?
    // 말 그대로 객체가 '복사'되길 원하는 특징 때문
    // TODO ) 동적 할당에서 자세히 등장
    Position& operator=(const Position& arg) // 자기 자신과 동일한 타입을 매개변수로 받는 연산자를 '복사 대입 연산자' 라고 한다. // 참조값을 반환할때는 어지간해서는 매개변수에 const를 붙여주는것이 안전하다. 임시객체를 참조하지 못하는 상황일때 const를 붙여주면 정상동작
    {
        _x = arg._x;
        _y = arg._y;
        return *this;
    }

    Position& operator++() // ++을 연속적으로 호출하기 위해 자기 자신 참조 타입
    {
        _x++;
        _y++;
        return *this;
    }

    Position operator++(int) // 원본은 건드리지 않고 사용하는 곳에만 증가시키키 위한 복사 값
    {
        Position ret = *this; // 건네줄 값을 임시적으로 저장
        _x++;
        _y++;
        return ret; // 위에서 증가된 값이 원본에 영향을 주지 않기 위해 저장해둔 기존 복사 값을 반환
    }

public:
    int _x;
    int _y;
};

Position operator+(int a, const Position& b)
{
    Position ret;

    ret._x = b._x + a;
    ret._y = b._y + a;

    return ret;
}

int main()
{
    Position pos;
    pos._x = 0;
    pos._y = 0;

    Position pos2;
    pos2._x = 1;
    pos2._y = 1;

    Position pos3 = pos + pos2;
    pos3 = pos.operator+(pos2); // 위와 같은 동작. 문법 차이 (초기화, 대입 차이도 있지만 문법 차이를 보여주기 위한 라인)

    Position pos4 = pos3 + 1;

    bool isSame = (pos3 == pos4);

    Position pos5;
    pos3 = (pos5 = 5);

    // Position& operator=(Position& arg) => (Pos&)을 원하지만 받은건 (Pos)의 복사값. (Pos&)로 참조하여 넘겨준다는 것은 그것을 수정하겠다는 의미가 내포되어있다. 하지만 (Pos)는 복사하는 용도로만 사용이 되고 이후에 종료됨.
    // Position& operator=(const Position& arg) => const를 붙이게 되면 원하는 값이 완전히 일치하지는 않아도 (Pos)의 복사값인 임시객체를 건네주면 그 값만 참조해서 꺼내주는 용도로 const를 붙인것이고, 수정하지 않겠다는 의미이므로 사용해도 무방하여 문법적으로 통과됨
    pos5 = pos3++;
    ++(++pos3);

    return 0;
}

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 - 인프런 | 강의
 
C++ 카테고리의 글은 인프런 Rookiss님의 강의를 공부하며 정리하는 내용입니다.
이미 알고 있는 내용도 다시 정리 되어있을 수 있습니다.

 

모든 글은 제가 공부하기 위해 작성합니다.

'Develop > C++' 카테고리의 다른 글

[C++] 동적 할당 #1  (0) 2022.10.06
[C++] 객체지향 마무리  (0) 2022.10.06
[C++] 초기화 리스트  (0) 2022.10.05
[C++] 다형성 #1 ~ 2  (0) 2022.09.28
[C++] 은닉성  (0) 2022.09.21