1. 개념


연산자는 기본 타입에 대하여는 정의되어 있지만, 내가 정의한 클래스에 대해서는 정의되어 있지 않다.



연산자 재정의를 하면 내가 정의한 클래스에서도 연산자를 쓸 수 있게 된다.


C++에서는 아래의 연산자를 재정의 할 수 있다.

+, -, *, /, %, ^, &, |, ~, !, =, <, >, +=, -=, *=, /=, %=, |=, <<, >>, >>=, <<=, ==, != <=, >=, &&, ||, ++, --, ,, ->*, ->, ( ), [ ]

C++ 20 추가: <=>



이 경우 Line 12은 x3 = x1.operator+(x2);로 동작한다.



2. 구현



연산자 오버로딩은 멤버 함수로 하는 방법과 일반 함수로 하는 두 가지 방법이 있다.



이때 일반 함수로 하는 경우는 인자가 하나 추가되고, (멤버함수인 경우 첫번째 인자는 *this가 된다)

private member variable에 접근하기 위해 friend 구문을 추가해야 한다.


둘 중에 뭐가 더 좋은지에 대해서는 찾아보면 정답은 없는 것 같다.


전에 들은 강의에서는 멤버 변수가 변하는 경우 멤버 함수로, 멤버 변수가 변하지 않으면 일반 함수로 한다는 이야기가 있었다.


링크에서는 질문자가 "일반 함수가 더 선호되는 이유"를 묻고 있다. 이때 답변이 지적하는 부분은 


"일반 함수로 하는 경우, 서로 다른 자료형에 대해 재정의 가능하다" 이다.


예를 들어, 위의 Point에 대해서 (숫자 * Point)를 Point의 x, y에 숫자 만큼 곱하는 걸로 정의하고 싶을 경우, 멤버 함수로는 구현이 불가능하지만 일반 함수로는 아래와 같이 구현 가능하다.



전위연산자와 후위연산자


전위연산자와 후위연산자 둘 다 operator++ 으로 이름이 똑같은데, 둘을 구분하기 위해 후위연산자는 operator++(int) 로 써야 한다. (이때 int는 구분을 위한 기능만 있을 뿐 실제 인자는 아니다.)


즉, 전위연산자는 T& operator++();

후위연산자는 T& operator++(int);



이때, 후위연산자 정의에 전위연산자를 사용하면, 증가연산자를 바꿔야 할 때, 전위연산자만 바꾸면 후위연산자도 같이 바뀌게 되므로 유지보수성을 좋게 할 수 있다.


3. 주의


::, . (멤버 변수/함수 접근), .*, ? 연산자는 오버로딩 할 수 없다.


=, (), [], -> 는 멤버 함수로만 구현할 수 있다.



참조

https://en.cppreference.com/w/cpp/language/operators

https://stackoverflow.com/questions/4622330/operator-overloading-member-function-vs-non-member-function

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture_series&no=52



'프로그래밍 > C++' 카테고리의 다른 글

가상 함수 (Virtual Function)  (0) 2018.10.23
상속 (Inheritance)  (0) 2018.10.22
this 포인터  (0) 2017.11.13
상수 멤버 함수 (const member function)  (0) 2017.11.13
정적 멤버 함수 (Static member function)  (0) 2017.11.13

+ Recent posts