연산자 오버로딩

연산자 오버로딩은 객체 지향 컴퓨터 프로그래밍에서 다형성의 특정 경우로 다른 연산자들이 함수 인자를 통해서 구현을 할 때를 말한다. 연산자 오버로딩은 일반적으로 언어, 프로그래머, 또는 두 가지 모두에 의해 정의된다.
연산자 오버로딩은 프로그램 개발자가 "가까운 목표 범위(closer to the target domain)" 표기법을 사용할 수 있고 사용자 정의 타입과 비슷한 수준을 허락하기 때문에 언어에 내장된 형식으로 구문을 지원한다. 그것은 쉽게 함수 호출을 사용하여 모방할 수 있다; 예를 들어, 정수 a, b, c를 생각하면:
a + b * c
연산자 오버로딩을 지원하는 언어에서, '*' 연산자는 '+' 우선 순위보다 높고, 이것은 효과적으로 좀 더 간결한 작성 방법일 것이다:
add (a, multiply (b,c))

예시

사용자 정의 유형의 "Time"에 추가 허용하는 연산자 오버로딩의 예시 (C++에서):
 Time operator+(const Time& lhs, const Time& rhs) {
     Time temp = lhs;
     temp.seconds += rhs.seconds;
     if (temp.seconds >= 60) {
         temp.seconds -= 60;
         temp.minutes++;
     }
     temp.minutes += rhs.minutes;
     if (temp.minutes >= 60) {
         temp.minutes -= 60;
         temp.hours++;
     }
     temp.hours += rhs.hours;
     return temp;
 }
덧셈은 왼쪽과 오른쪽 피연산자를 의미하는 이항 연산이다. C++에서, 전달되는 인자는 피연산자이며, 임시 개체가 반환 값이다.
연산자는 또한 클래스 메서드를 정의할 수 있으며, 숨겨진 this 인수로 lhs를 대체한다. 그러나 이것은 왼쪽 피연산자 타입 Time의 효과와 this는 수정 가능하게 될 수 있는 lvalue(왼쪽 값)을 추정한다.
 Time Time::operator+(const Time& rhs) const {
     Time temp = *this;  /* 'this' 값 복사, 이것은 수정되지 않는다. */
     temp.seconds += rhs.seconds;
     if (temp.seconds >= 60) {
         temp.seconds -= 60;
         temp.minutes++;
     }
     temp.minutes += rhs.minutes;
     if (temp.minutes >= 60) {
         temp.minutes -= 60;
         temp.hours++;
     }
     temp.hours += rhs.hours;
     return temp;
 }
this에서 작동되는 클래스 메서드로 정의된 단항 연산자는 명백한 인수를 받을 일은 없을 거라고 한다:
 bool Time::operator!() const {
     return ((hours == 0) && (minutes == 0) && (seconds == 0));
 }

비평

그것은 프로그래머가 연산자에 따라 그것들의 피연산자의 유형에 완전히 다른 의미를 줄 수 있기 때문에 연산자 오버로딩은 종종 비판을 받아왔다. 예를 들어 C++에서 <<의 사용:
a << 1
a는 정수 형식의 경우 1 비트로 남아있는 변수 a의 비트를 쉬프트한다, 하지만 만약 a는 출력 스트림일 경우 그러면 위의 코드는 스트림에 "1" 쓰기를 시도한다. 연산자 오버로딩은 원래 프로그래머가 연산자의 일반적인 의미를 변경하는 놀라운 후속 프로그래머를 잡을 수 있기 때문에, 그것은 일반적으로 신경을 써서 연산자 오버로딩을 사용하는 것은 좋은 습관으로 간주된다.
이 비판에 대한 일반적인 답변은 동일한 인자뿐 아니라 오버로딩을 함수에 적용되는 것이다. 또한, 심지어는 오버로딩이 없는 상태에서, 프로그래머는 이름에서 예상되는 것과 완전히 다른 일을 하는 함수를 정의할 수 있다. 남아있는 문제는 그 언어와 같은 C++ 연산자 기호의 제한된 집합을 제공하고, 따라서 프로그래머의 새로운 작업에 대한 보다 적절한 연산자 기호를 선택 옵션에서 제거한다.
또, 연산자와 함께 더 많은 미묘한 문제는 수학에서 특정 규칙이 잘못 예상 또는 실수로 간주 될 수 있다는 것이다. 예를 들면 +의 교환 법칙 (예:  a + b == b + a ) 이 항상 적용되지 않는다; 피연산자가 문자열일 때 이 예제가 발생한다, +는 일반적으로 오버로딩이 있기 때문에 문자열 연결을 수행한다. (예: "school" + "bag"은 "schoolbag"을 산출, 이것은 "bag" + "school"은 "bagschool"을 산출하는 것과 다르다). 일반 계산 인수로 수학에서 직접 제공한다: + 는 정수에서 교환법칙이 성립 (그리고 일반적으로 어떠한 실제 숫자) 하는 동안, 그것은 변수의 다른 "종류"에 대한 교환법칙이 성립하지 않는다. 반올림 오류로 인해 실제 부동 소수점 값에서 그것은 그 + 도 연관되지 않다고 더 지적할 수 있다. 또 다른 예를 들어: 이항연산 * (곱셈) 은 정수에 대한 교환법칙이 성립하지만, 행렬 곱셈의 경우 교환법칙이 성립하지 않는다.

1960년대

ALGOL 68 기능은 연산자 오버로딩을 허용한다.
연산자 오버로딩 ¬, =, ≠ 그리고 abs가 정의된 ALGOL 68 언어 기능 (페이지 177)에서 추출:
10.2.2. 부울 피연산자에 대한 연산
a) op ∨ = (bool a, b) bool:( a | true | b );
b) op ∧ = (bool a, b) bool: ( a | b | false );
c) op ¬ = (bool a) bool: ( a | false | true );
d) op = = (bool a, b) bool:( a∧b ) ∨ ( ¬b∧¬a );
e) op ≠ = (bool a, b) bool: ¬(a=b);
f) op abs = (bool a)int: ( a | 1 | 0 );
특별한 선언이 연산자를 오버로드하기 위해 필요하지 않는다는 점을 참고하고, 프로그래머는 새로운 연산자를 자유롭게 만들 수 있다.

1980년대

에이다는 에이다 83 언어 표준의 출판과 함께 처음 소개됨에서 연산자 오버로딩을 지원한다. 그러나, 언어의 설계자는 새로운 연산자의 정의를 허용하지 않도록 선택한다: 단지 언어의 기존 연산자 (예 : "+", "*", "and" 등 식별자 새로운 기능을 정의하여)를 오버로딩할 수 있다. 언어의 후속 개정 (​​1995년과 2005년)은 기존 연산자의 오버로딩에 대한 제한을 유지한다.
C++의 연산자 오버로딩은 ALGOL 68에서 더 수정되었다.

1990년대

Sun은 자바 언어로 오버로딩 연산자를 포함하지 않기로 선택한다.

2001년

마이크로소프트는 C#에서 연산자의 오버로딩을 포함했다.