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

2022. 3. 8. 13:43Languages/C++

/*  본 글은 <씹어먹는 C++> 글을 참고하여 공부한 글입니다.  */

 

 

 

연산자 오버로딩(Operator  Overloading)

 

오버로딩 (Overloading)

 

  • 객체지향언어에서 나오는 개념으로, 동일한 이름이지만 여러 개를 정의할 수 있는 것을 말한다.
  • 대표적으로 함수 오버로딩이 있음
  • C++에서는 연산자 또한 오버로딩을 적용할 수 있다.
    • 범위지정 연산자(::)멤버 지정 연산자(.)멤버 포인터 지정 연산자 (.*)는 오버로딩할 수 없다.
    • 기본적으로 제공되는 자료형에 적용할 때는 사용할 수 없다.
    • 비정적 클래스 멤버 함수 또는 전역 함수이어야 한다.

 

오버로딩 가능한 연산자들

 

  • 산술 연산자 (+, -, *, ...)
  • 비교 연산자 (==, !=, ...)
  • 대입 연산자 (=)
  • 복합산술 연산자 (+=, -=, ..)
  • 논리 연산자 (&&, ||, ..)
  • 멤버 선택 연산자 (->, *(역참조))
  • 증감 연산자 (++, --)
  • 배열 및 함수 호출 연산자 ([ ], ( ))

 

연산자 오버로딩 선언 및 내부 처리

 

선언 형태

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

 

만약 클래스 A가 있다고 한다면, 클래스 A 객체간의 덧셈 연산자 오버로딩은 다음과 같이 적을 수 있다.

class A {
private:
    int data;

public:
    A(int data) : data(data) {}
    A operator+(const A& a) const;
    void Println() { std::cout << data << std::endl; }
};

A A::operator+(const A& a) const {
    A newA(data + a.data);
    return newA;
}

 

그러면 다음과 같이 사용하게 될 텐데,

A a1(10), a2(20);
A result = a1 + a2;
result.Println();    // 30 출력

 

위 문장은 사실상 컴파일러가 내부적으로 다음과 같이 변환하여 처리한다.

A a1(10), a2(20);
A result = a1.operator+(a2);  // 내부적으로 처리
result.Println();

 

즉, 해당 객체의 연산자 함수가 호출되는 걸 볼 수 있다.

이런 방식이기 때문에 오버로딩이 가능한 게 아닌가라는 생각이 들긴 했다.

 

 

암시적 형변환을 이용한 오버로딩 방법

 

현재 A 클래스에는 객체와 정수 자료형 값과의 연산자가 정의되어 있지 않다. 하지만 다음 문장은 오류없이 제대로 실행된다.

A a1(10);
A result = a1 + 20;
result.Println();    // 30 출력

 

다시 내부적으로 처리되는 걸 적어보면 다음과 같다.

A result = a1.operator+(20);

 

처음에는 당연히 해당 연산자에 대한 정의가 없기 때문에 바로 실행되지는 않는다.

그래서 컴파일러는 변환을 할만한 생성자가 없는지를 살펴본다.

A(int data) : data(data) {}

 

즉, 아까 위의 코드는 다음과 같이 변환되어 실행된 것이다.

A result = a1.operator+(A(20));

 

원래라면 A operator+(int a) 이런 식의 연산자 오버로딩 또한 만들어줘야 했겠지만, 이런 방법을 이용하여 작업을 줄일 수도 있을 것 같다. 연산자 오버로딩 함수의 호출을 알았다면, 당연히 다음처럼 사용하면 오류가 발생한다.

A a1(10);
//A result = 20 + a1;   오류

 

 

 

728x90
반응형