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 |