C++ 연산자 오버로딩 기초

C++의 연산자 오버로딩(Operator Overloading)은 사용자 정의 타입(클래스, 구조체)에 대해 표준 연산자(+, -, *, << 등)의 동작을 재정의하는 기능이다.

이를 통해 객체를 기본 자료형처럼 직관적으로 다룰 수 있다.

산술 연산자 오버로딩 (+)

좌표를 나타내는 Point 클래스에서 두 객체를 더하는 연산자를 정의한다.

#include <iostream>

class Point {
private:
    int x, y;
public:
    Point(int x = 0, int y = 0) : x(x), y(y) {}

    // + 연산자 오버로딩 (멤버 함수 방식)
    Point operator+(const Point& other) const {
        return Point(this->x + other.x, this->y + other.y);
    }

    void display() const {
        std::cout << "(" << x << ", " << y << ")" << std::endl;
    }
};

int main() {
    Point p1(10, 20);
    Point p2(5, 5);

    // 객체 간의 직관적인 연산 가능
    Point p3 = p1 + p2; 
    p3.display(); // (15, 25)

    return 0;
}

출력 연산자 오버로딩 (<<)

std::cout을 통해 객체를 즉시 출력할 수 있도록 << 연산자를 오버로딩한다.

이 연산자는 대개 friend 함수로 정의한다.

#include <iostream>

class Point {
    int x, y;
public:
    Point(int x, int y) : x(x), y(y) {}

    // 전역 함수 방식의 오버로딩 (friend 선언으로 private 멤버 접근 허용)
    friend std::ostream& operator<<(std::ostream& os, const Point& p) {
        os << "Point(" << p.x << ", " << p.y << ")";
        return os;
    }
};

int main() {
    Point p(10, 20);
    // 함수 호출 대신 직관적인 출력 가능
    std::cout << "Result: " << p << std::endl; 
    return 0;
}

주요 규칙 및 주의사항

  • 우선순위 유지: 연산자의 원래 우선순위와 결합 법칙은 바뀌지 않는다.
  • 피연산자 개수: 기존 연산자가 가진 피연산자의 개수를 변경할 수 없다.
    (예: 이항 연산자를 삼항으로 바꿀 수 없음)
  • 새로운 연산자 생성 불가: **<>와 같이 기존에 없는 연산자를 새로 만들 수는 없다.
  • 직관성 유지: + 연산자가 뺄셈을 수행하게 만드는 등 연산자의 본래 의미를 훼손하는 오버로딩은 지양해야 한다.

P.S

연산자 오버로딩은 코드의 가독성과 표현력을 높여주는 강력한 기능이다.

하지만 과도하거나 부적절한 사용은 코드의 모호성을 높일 수 있으므로, 연산이 자연스러운 상황에만 제한적으로 적용하는 설계적 안목이 필요하는 것 같다.

Author avatar

웨이호프

WordPress creator and blogger.

View all posts