350 likes | 640 Views
Overloading. CMPS 2143. Overloading. A term is overloaded if it has many different meanings many English words are : eg . blue In programming languages, it is usually function and method names and operators Also known as ad hoc polymorphism
E N D
Overloading CMPS 2143
Overloading • A term is overloaded if it has many different meanings • many English words are : eg. blue • In programming languages, it is usually function and method names and operators • Also known as ad hoc polymorphism • may be used in non-OO languages (hence the inclusion of functions)
Overloading vs Overriding • Both take a function or method named in an invocation and select for execution one out of potentially many different function/method implementations • Differences • Overloading performed at compile time (early binding) • determined based on different signatures • Overriding performed at runtime (late binding) • signatures the same, so based on dynamic values
Type Signatures • Key to understanding overloading • Used by compiler to determine correct function or method to call • Description of argument types, their order, the return type • overloaded methods – omit the type of receiver from the signature, but it is understood and determined by the context of the call • double power (double base, int exponent) • has signature double x int double
Scope • 2nd key idea is scope – defines the portion of a program in which the name can be used • name has meaning within braces of a function • outside class declaration, if method not public, it has no meaning • At any time in the static (textual) representation of a program there can be multiple active scopes • within the class, then within a method in the class
2 broad categories of overloading • 2 methods with same name and possibly same signature (as long as they are in different classes) • different scopes • if you use both classes, use Classname::methodname() to distinguish • 2 methods with same name, but different signatures • regardless of scope
Overloading based on Type signatures • procedures, functions, methods are allowed to share a name • Disambiguated by number, order, and in statically typed languages, the type of arguments they require • EVEN IF THEY SHARE THE SAME SCOPE • Occurs in C++, C#, Java, Delphi Pascal, CLOS, Ada, and many functional languages • Good example is the overloading of the constructor methods • default, parameterized, and copy constructors
Can do with other methods class Example { int sum (int a) {return a;} int sum (int a, int b) {return b;} int sum (int [] list, int n) { int tot=0; for (int i=0; i< n; i++) tot += list[i]; return sum; } };
OPERATOR OVERLOADING • Some languages allow operator overloading • Java does not • Giving the normal C++ operators such as +, -, * , <=, and += etc. , additional meanings when they are applied to user-defined types (classes) • You cannot create new operators like *& and try to overload them; only existing operators can be overloaded
OPERATOR OVELOADING • The precedence of an existing operator cannot be changed by overloading • The associativitycannot be changed • The arity(number of arguments) cannot be changed • The meaning of how an operator works on built-in types cannot be changed • Operator overloading works only on objects of user defined types or with a mixture of user-defined and built-in types • At least one argument of an operator function must be a class object or a reference to a class object
OPERATOR OVERLOADING • Operators that cannot be overloaded • “::” , “ ?: ” , “ .” • Operators that can be used without overloading • “ = ” “ , ” “&” • Operator functions can be member functions or global friendfunctions • I will discuss friends later
Creating a Member Operator Function return-type class-name::operator # (arg-list) { //operations } Creating a Global Operator Function • return-type operator # (arg-list) { //operations }
OVERLOADING UNARY OPERATORS class Counter{ private: int count; public: Counter() {count=0; } int getcount() {return count;} void operator ++() { ++count;} }; // END OF CLASS void main() { Counter c1, c2; cout<< “\nc1 = “ << c1.getcount(); cout << “\nc2 = “ << c2.getcount(); ++c1; //prefix ++c2; //prefix ++c2; //translated to // c2.operator++() by compiler cout << “\nc1 = “ << c1.getcount(); cout << “\nc2 = “ << c2.getcount();
OPERATOR RETURN VALUES In the previous example, you cannot write c1=++c2; //Error;Why? Counter operator ++() { ++count; Counter temp; temp.count=count; return temp; }
POSTFIX NOTATION • Counter operator ++(int) • { • return Counter(count++); • } • The only difference is in the int in the parenthesis • This isn’t really an argument, and it doesn’t mean an integer • It is simply a signal to the compiler to create a postfix version of the operator
OVERLOADING BINARY OPERATORS class StringExt : public Object { public: //constructors StringExt(); StringExt(string s); StringExt(constStringExt & other); //overloaded + for concatenation StringExtoperator + (StringExt se); StringExtoperator + (int i); StringExtoperator + (double r); StringExtoperator + (string s); //overloaded = for assignment void operator = (string s); void operator = (StringExt se); //returns the string equivalent of the StringExt virtual string toString (); private: string val; };
OVERLOADING BINARY OPERATORS StringExt::StringExt (constStringExt & other) : Object("StringExt") {val = other.val;} StringExtStringExt::operator + (StringExt se) { StringExt result(val); result.val.append (se.val); return result; } void StringExt::operator = (StringExt se) {val = se.val;}
OVERLOADING BINARY OPERATORS #include “StringExt.h” void main() { StringExt se1(“Hi”), se2(“Howdy”), se3, se4; se3 = se1 + se2; //same as se1.operator + (se2) se4 = se1+ se2 + e3; //note cascading se4.toString(); }
In se3 = se1 + se2; • The argument on the LEFT side of the + operator (se1 in this case) is the receiverobjectof which the operator is a member. • The argument on the RIGHT side of the + operator (se2 in this case) must be furnished as an argument to the operator • The operator returns a value which can be assigned or used in other ways; in this case it is assigned to se3 (using another overloaded operator =) • An overloaded operator implemented as a member function always requires one less argument than its no. of operands, since one operand is the object of which the operator is a member (that is, it is the receiver object of the message). • That is why unary operators require no arguments.
Creating non-member overloaded methods #include “StringExt.h” //prototypes:I/O for programmer-defined class StringExt ostream & operator << (ostream & cout, StringExt se); istream& operator >> (istream & cout, StringExt & se); // Implementations I/O for programmer-defined types ostream& operator << (ostream & cout, StringExt se) { cout << se.toString(); return cout; }
Creating non-member overloaded methods istream & operator >> (istream & source, StringExt & se) { string s; source >> s; StringExtse2(s); se = se2; return source; }
Using non-member overloaded methods void getStringExt (string prompt, StringExt & x) { cout<< prompt; cin>> x; }
Coercion and conversion • integer + is radically different from floating-point + • Sometimes overloading is NOT the only activity occurring, sometimes coercion goes on, especially with arithmetic operations • occurs when we have mixed types • In my example se+i or se+se or se+d or se+s • no coercion occurs, just overloading • If we had se + se and s + s, and no se + s • then s could be coerced to an se • even s+s could coerce both s to se
Substitution as conversion • coercion – change in type • principle of substitution introduces a form of coercion found in OOP languages • Could use inheritance • or implement an interface • StringExt didn’t use inheritance from string • used composition
Overloading and Inheritance in Java • Java has some subtle interactions • If two or more methods have the same name and number of parameters, the compiler uses algorithm to determine match • find all methods that could possible apply to the method call and if one matches argument types exactly, use that one. • if a method’s parameter types are all assignments to any other method in the set, then eliminate the second method • If exactly one method remains, use it, else give compiler error
Example: • Dessert, Pie, Cake, ApplePie, and ChocolateCake void order (Dessert d, Cake c); void order (Pie p, Dessert d); void order (ApplePie a, Cake c); order (aDessert, aCake); //legal - 1 order (anApplePie, aDessert); //legal - 2 order (aDessert, aDessert); //illegal //all eliminated in step 1, can’t downcast order (anApplePie, aChocolateCake); //legal //all in set 1, but 1,2 eliminated in step 2, //leaving 3 order (aPie, aCake); //illegal //3 elim. in step 1, but 2 and 3 survive step 2
Conversion • C++ gives programmer control over how an instance of a class can be implicitly converted to another type • use a constructor with a single argument • rule to compiler to convert arg type to class type class ComplexNumber { public: ComplexNumber(); ComplexNumber(double r, double i); ComplexNumber (double r); : } ComplexNumber::ComplexNumber (double r) { real = r; imag = 0; }
ComplexNumber c(4.5,3.2); ComplexNumber result; double r = 5; result = c + r; //r will be converted to a //ComplexNumber and ComplexNumber + //will be performed
Conversion in other direction • Make a Fraction a double. class Fraction { public: : operator double() { return numerator() / (double) denominator(); } }; Fraction f(2, 3); double d = f * 3.14; • Coerce ComplexNumber to double ?
Redefinition • Child class defines a method using same name as method in parent class, BUT with a different type signature • so NO overriding here • Ho hum? NO – depends on language • Two different techniques • merge model (Java) • creates a set and all possibilities are examined • hierarchical model (C++) • determines which to use from inner scope outward
Polyadicity • A polyadic function is one that can take a variable number of arguments • cout << “sum is “” << sum << endl; • Easy to write the call • More difficult to write the body • C++ uses an ad hoc method (involving a list, 3 methods, ellipsis • C# has a more elegant solution • public void Write (params object [ ] args) {…}
Study Questions • pg. 307: 11-7, 10 • program 4 extra credit: • add the conversion for a double to a complex number and another case to your menu options and switch • turn in program 4 a week early