연산자 오버로딩

**연산자 오버로딩**(operator overloading)은 객체 지향 컴퓨터 프로그래밍에서 다형성의 특정 경우로 다른 연산자들이 함수 인자를 통해서 구현을 할 때를 말한다. 연산자 오버로딩은 일반적으로 언어, 프로그래머, 또는 두 가지 모두에 의해 정의된다. 연산자 오버로딩은 프로그램 개발자가 "가까운 목표 범위(closer to the target domain)" 표기법을 사용할 수 있고url-status=dead 사용자 정의 타입과 비슷한 수준을 허락하기 때문에 언어에 내장된 형식으로 구문을 지원한다. 그것은 쉽게 함수 호출을 사용하여 모방할 수 있다; 예를 들어, 정수 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"`을 산출하는 것과 다르다). 일반 계산 인수로 수학에서 직접 제공한다: + 는 정수에서 교환법칙이 성립 (그리고 일반적으로 어떠한 실제 숫자) 하는 동안, 그것은 변수의 다른 "종류"에 대한 교환법칙이 성립하지 않는다. 반올림 오류로 인해 실제 부동소수점 값에서 그것은 그 + 도 연관되지 않다고 더 지적할 수 있다. 또 다른 예를 들어: 이항연산 * (곱셈) 은 정수에 대한 교환법칙이 성립하지만, 행렬 곱셈의 경우 교환법칙이 성립하지 않는다.
# 목록
몇 가지 일반적인 프로그래밍 언어의 분류는 프로그래머와 연산자가 미리 정의된 집합으로 오버로드 가능 여부를 나타낸 것이다. {| class="wikitable" |- ! 연산자 ! 오버로딩 불가능 ! 오버로딩 가능 |- ! 신규 정의 | * ML * Pico상징적인 이름으로 바이너리 기능 삽입을 호출할 수 있다 * 프롤로그 | * ALGOL 68 * Eiffel * 포트란포트란 90에서 소개 * F# * 하스켈오버로딩의 유형 클래스를 대신함 * 아이오 * 펄 6 * R * 스칼라 * 스몰토크 |- ! 제한된 집합 | * C * 자바 * 자바스크립트 * 모듈라-2 * 오브젝티브-C * 파스칼 * 베이직 | * 에이다 * C++ * C# * D * 프리베이직 * 그루비 * 루아 * 델파이 (2005년) * 오브젝트 파스칼 (프리 파스칼url-status=dead) * PHP (magic 메서드이나 ArrayAccess 인터페이스나 운영자 확장을 사용) * 펄 * 파이썬 * 루비 * 비주얼 베이직 2005 * 코틀린 |}
# 연산자 오버로딩의 연대순

## 1960년대
ALGOL 68 기능은 연산자 오버로딩을 허용한다.url-status=dead 연산자 오버로딩 ¬, =, ≠ 그리고 **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에서 더 수정되었다.accessdate= April 2007
## 1990년대
Sun은 자바 언어로 오버로딩 연산자를 포함하지 않기로 선택한다.
## 2001년
마이크로소프트는 C#에서 연산자의 오버로딩을 포함했다.