Operator overloading
Polymorphism |
---|
In object-oriented programming, operator overloading—less commonly known as operator ad hoc polymorphism—is a specific case of polymorphism, where different operators have different implementations depending on their arguments. Operator overloading is generally defined by the language, the programmer, or both.
Operator overloading is used because it allows the developer to program using notation closer to the target domain[1] and allows user-defined types a similar level of syntactic support as types built into the language. It is common, for example, in scientific computing, where it allows computational representations of mathematical objects to be manipulated with the same syntax as on paper.
Object overloading can be emulated using function calls; for example, consider the integers a, b, c:
a + b * c
In a language that supports operator overloading, and with the usual assumption that the '*' operator has higher precedence than '+' operator, this is a concise way of writing:
add (a, multiply (b,c))
However, the former syntax reflects common mathematical usage.
Examples
In this case, the addition operator is overloaded to allow addition on a user-defined type "Time" (in C++):
Time operator+(const Time& lhs, const Time& rhs) { Time temp = lhs; temp.seconds += rhs.seconds; temp.minutes += temp.seconds / 60; temp.seconds %= 60; temp.minutes += rhs.minutes; temp.hours += temp.minutes / 60; temp.minutes %= 60; temp.hours += rhs.hours; return temp; }
Addition is a binary operation, which means it has left and right operands. In C++, the arguments being passed are the operands, and the temp
object is the returned value.
The operation could also be defined as a class method, replacing lhs
by the hidden this
argument; however this forces the left operand to be of type Time
and supposes this
to be a potentially modifiable lvalue:
Time Time::operator+(const Time& rhs) const /* const means that 'this' is not to be modified */ { Time temp = *this; /* Copy 'this' which is not to be modified */ temp.seconds += rhs.seconds; temp.minutes += temp.seconds / 60; temp.seconds %= 60; temp.minutes += rhs.minutes; temp.hours += temp.minutes / 60; temp.minutes %= 60; temp.hours += rhs.hours; return temp; }
Note that a unary operator defined as a class method would receive no apparent argument (it only works from this
):
bool Time::operator!() const { return ((hours == 0) && (minutes == 0) && (seconds == 0)); }
Less than(<) operator is often overloaded to sort a structure or class.
class pair { public: int x,y; bool operator < ( const pair& p ) const { if(x==p.x) return y<p.y; return x<p.x; } };
Note that in last example operator overloading is done within the class which is same as previous examples. In C++ after overloading less than operator(<), builtin sort functions can be used to sort some classes.
Criticisms
Operator overloading has often been criticized[2] because it allows programmers to give operators completely different semantics depending on the types of their operands. For example, the use of the <<
in C++'s:
a << 1
shifts the bits in the variable a left by 1 bit if a is of an integer type, but if a is an output stream then the above code will attempt to write a "1" to the stream. Because operator overloading allows the original programmer to change the usual semantics of an operator and to catch any subsequent programmers by surprise, it is considered good practice to use operator overloading with care ( Java developers decided not to use this feature.[3]).
The common reply[citation needed] to this criticism is that the same argument applies to function overloading as well. Furthermore, even in the absence of overloading, a programmer can define a function to do something totally different from what would be expected from its name. An issue that remains is that languages such as C++ provide a limited set of operator symbols, thus removing from programmers the option of choosing a more suitable operator symbol for their new operation.
Another, more subtle, issue with operators is that certain rules from mathematics can be wrongly expected or unintentionally assumed. For example, the commutativity of + (i.e. that a + b == b + a
) does not always apply; an example of this occurs when the operands are strings, since + is commonly overloaded to perform a concatenation of strings (i.e. "school" + "bag"
yields "schoolbag"
, which is different from "bag" + "school"
yields "bagschool"
). A typical counter[citation needed] to this argument comes directly from mathematics: While + is commutative on integers (and most generally any complex numbers), it is not commutative for other "types" of variable. It can be further noted that + is, in practice, not associative even with floating-point values, due to rounding errors. Another example: binary * (multiplication) is commutative for integers but not commutative in matrix multiplication.
Catalog
A classification of some common programming languages is made according to whether their operators are overloadable by the programmer and whether the operators are limited to a predefined set.
Operators | Not overloadable | Overloadable |
---|---|---|
New definable | ||
Limited set |
Timeline of operator overloading
1960s
The ALGOL 68 specification allowed operator overloading.[11]
Extract from the ALGOL 68 language specification (page 177) where the overloaded operators ¬, =, ≠ and abs are defined:
10.2.2. Operations on Boolean Operands 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 );
Note that no special declaration is required to overload an operator, and the programmer is free to create new operators.
1980s
Ada supports overloading of operators from its inception, with the publication of the Ada 83 language standard. However, the designers of the language chose not to permit the definition of new operators: only the existing operators in the language may be overloaded (by defining new functions with identifiers such as "+", "*", "and" etc.). Subsequent revisions of the language (in 1995 and 2005) maintain the restriction to overloading of existing operators.
C++'s operator overloading is further refined from that of ALGOL 68's.[12]
1990s
Sun chooses not to include operator overloading in the Java language.[13][14][15]
Ruby allows operator overloading as syntactic sugar for simple method calls.
Lua allows operator overloading as syntactic sugar for method calls with the added feature that if the first operand doesn't define that operator, the method for the second operator will be used.
2000s
Microsoft includes operator overloading for C# in 2001.
Scala treats all operators as methods and thus allows operator overloading by proxy.
References
- ↑ "C++ FAQ Lite: What are the benefits of operator overloading?". June 2010. Retrieved August 2010.
- ↑ Issues in Overloading
- ↑ Features Removed from C and C++
- ↑ binary functions with a symbolic name can be called infix
- ↑ introduced in Fortran 90
- ↑ type classes instead of overloading
- ↑ "Why does Go not support overloading of methods and operators?". Retrieved 4 September 2011.
- ↑ "Operator Overloading, Free Pascal Manual". Retrieved June 2011.
- ↑ "Implementing Operators for Your Class". Retrieved October 2013.
- ↑ "Operator Overloading, Delphi Manual". Retrieved July 2013.
- ↑ A. van Wijngaarden, B.J. Mailloux, J.E.L. Peck and C.H.A. Koster, et al. (August 1968). "Report on the Algorithmic Language ALGOL 68, Section 10.2.2." (PDF). Retrieved April 2007.
- ↑ Bjarne Stroustrup. "A History of C++: 1979−1991 - page 12" (PDF). Retrieved April 2007.
- ↑ comp.lang.java FAQ Question 6.9: Why isn't there operator overloading?
- ↑ java.sun.com
- ↑ Holzner, Steven (2001). C++ : Black Book. Scottsdale, Ariz.: Coriolis Group. p. 387. ISBN 1-57610-777-9. "One of the nicest features of C++ OOP is that you can overload operators to handle objects of your classes (you can't do this in some other OOP-centric languages, like Java)."
See also
- Function overloading
- Polymorphism (computer science)
- Subroutine
- Operator (programming)
- Operators in C and C++