나만의 작은 도서관

[C++][Class] 연산자 오버로딩(Operator Overloading) 본문

C++/문법 및 메소드(STL)

[C++][Class] 연산자 오버로딩(Operator Overloading)

pledge24 2025. 3. 25. 23:44

연산자 오버로딩(Operator Overloading)

연산자 오버로딩

  • 연산자 오버로딩은 C++에서 기존의 연산자(+, -, *, /, == 등)를 사용자가 원하는 방식으로 동작하도록 재정의하는 것을 의미한다.
    • 즉, 연산자 오버로딩은 사용자 정의 연산자를 정의하기 위해 사용한다.
  • 연산자 오버로딩을 사용하면 객체 간 연산을 보다 직관적으로 처리할 수 있다.
    • 예를 들어, STL 컨테이너의 대표 컨테이너인 vector는 ‘>’와 같은 비교 연산자들을 오버로딩하여 서로의 크기를 비교할 수 있다. (자세한 내용은 여기 참고)
  • 대부분의 연산자들은 오버로딩이 가능하다. 심지어 [] (첨자 연산자), << (입출력 연산자), () (호출 연산자) 또한 가능하다.
    • 오버로딩을 할 수 없는 연산자로는 :: (범위 지정), . (멤버 지정),.* (멤버 포인터로 멤버 지정)이 있다.
  • 연산자 오버로딩은 정의한 위치에 따라 클래스 내의 멤버 함수로도, 전역 함수(비멤버 함수)로도 사용할 수 있다.

 

연산자 오버로딩 선언

(리턴 타입) operator(연산자) (연산자가 받는 인자)

// example
bool operator==(MyString& str);

 


멤버 연산자 함수

  • 특정 클래스 내에서 연산자를 오버로딩한 연산자 함수
  • 멤버 연산자 함수(operator 함수)는 왼쪽 피연산자(Left Hand Side, lhs)를 항상 자기 자신(this 포인터)으로 고정한다.
  • 멤버 연산자 함수를 정의하면 내부에서는 아래와 같이 변환하여 사용한다.
(lhs) OP (rhs) -> lhs.operatorOP(rhs)

// example
str1 == str2 -> str1.operator==(str2) // 연산자를 멤버 함수처럼 사용.

 

 

단항 연산자 오버로딩

  • 만약 오버로딩할 연산자가 "단항 연산자"일 경우, 후위 연산자(T++)는 매개변수 없이, 전위 연산자(++T와 같이)는 더미 매개변수를 하나 넣어주는 방식으로 구분한다. (넣어준 매개변수는 단순 연산자 구분용으로만 사용한다.)
A& operator++() { /* process A++ */ return *this; } // 후위 연산자**(T++)**
A operator++(int) { A temp(A); /* process ++A */ return temp; } // 전위 연산자**(++T)**

 

 

멤버 연산자 함수 예제

class Point {
public:
    Point(int x = 0, int y = 0) : _x(x), _y(y) {}

    // 멤버 변수로 '+' 연산자 오버로딩
    Point operator+(const Point& other);
    void printPoint() { cout << "Point : " << _x << " " << _y << '\\n';}
        
private:
    int _x, _y;
};

// 오버로딩한 '+' 멤버 연산자 함수 정의
Point Point::operator+(const Point& other) {
    return Point(x + other.x, y + other.y);
}

int main(void){

    Point p1(1, 2);
    Point p2(10, 11);

    Point p3 = p1 + p2; // 연산자 함수 사용
    p3.printPoint();

    return 0;
}

 

 

실행 결과

Point : 11 13

 


전역 연산자 함수

  • 특정 클래스의 멤버 함수가 아닌, 전역 범위에 정의한 연산자 함수.
  • 전역 연산자 함수는 해당 연산자를 사용할 때 피연산자 타입들이 일치할 때마다 오버로딩한 내용이 실행될 수 있다.

 

멤버 연산자 함수와의 차이점

  • 멤버 연산자 함수와 달리 전역 연산자 함수는 왼쪽 피연산자(lhs)와 오른쪽 피연산자(rhs)가 서로 다른 타입이어도 연산이 가능하다.
    • 예를 들어, 왼쪽 피연산자(lhs)가 객체 타입이 아닌 ‘3 + p’도 연산에 사용할 수 있다.
  • 멤버 연산자 함수와 달리 ‘[]’(첨자 연산자), ‘→’(멤버 접근 연산자), ‘()’(호출 연산자), ‘=’(대입 연산자)는 오버로딩 할 수 없다.
  • 멤버 연산자 함수와 달리 this가 존재하지 않아 this에 대응하는 피연산자 객체를 매개변수로 받는다.

 

 

단항 연산자 오버로딩

  • 만약 오버로딩할 연산자가 "단항 연산자"일 경우, 전역 연산자 함수는 멤버 연산자 함수의 this에 대응하는 피연산자 객체를 첫 번째 매개변수로 받는다.
A& operator++(A& a) { /*process A++*/ return *this; } // 후위 연산자**(T++)**
A operator++(A& a, int) { A temp(A); /*process ++A*/ return temp; } // 전위 연산자**(++T)**

 

 

전역 연산자 함수 예제 + 주의사항

  • 전역 연산자 함수는 각 객체의 private 멤버 변수에 접근할 수 없다. 따라서 객체가 전역 연산자 함수를 사용할 경우 객체는 해당 함수를 friend로 지정해야 한다.
💡 “friend” 키워드는 지정한 대상에게 private 멤버 변수를 사용할 수 있도록 열어주는 키워드입니다.
class Point {
public:
    Point(int x = 0, int y = 0) : x(x), y(y) {}

    // 전역 연산자 함수가 private 멤버 변수를 사용할 수 있도록 열어준다.
    friend Point operator+(const Point& a, const Point& b);
    void printPoint() { cout << "Point : " << x << " " << y << '\\n';}
    
private:
	int x, y;
};

// 전역 함수로 '+' 연산자 오버로딩
Point operator+(const Point& a, const Point& b) {
    return Point(a.x + b.x, a.y + b.y);
}

int main(void){

    Point p1(1, 2);
    Point p2(10, 11);

    Point p3 = p1 + p2;
    p3.printPoint();

    return 0;
}

 

 

실행 결과

Point : 11 13

 


참고 자료

https://www.exforsys.com/tutorials/c-plus-plus/how-to-access-class-members.html

https://www.geeksforgeeks.org/types-of-constructors-in-cpp/

https://stackoverflow.com/questions/4943958/conditions-for-automatic-generation-of-default-copy-move-ctor-and-copy-move-assi

https://modoocode.com/202

https://modoocode.com/203