220 likes | 347 Views
Recitation Week 4. Object Oriented Programming COP3330 / CGS5409. Today’s Recitation. Arithmetic Operator Overloading Increment (++) / Decrement (--) In-class exercise Assignment Two. Assignment Submission. Double check assignment submissions!!! 1/3 class programs did not compile!!!
E N D
Recitation Week 4 Object Oriented Programming COP3330 / CGS5409
Today’s Recitation • Arithmetic Operator Overloading • Increment (++) / Decrement (--) • In-class exercise • Assignment Two
Assignment Submission • Double check assignment submissions!!! • 1/3 class programs did not compile!!! • Visual Studio appending extra characters to submitted files
Operator Overloading • There are many operators available that work on built-in types, like int and double. • Operator overloading -- is the creation of new versions of these operators for use with user-defined types. • An operator in C++ is just a function that is called with special notation (usually more intuitive or familiar notation). Overloading an operator simply involves writing a function. • Operator overloading is done for the purpose of using familiar operator notation on programmer-defined types (classes).
Operator Overloading Rules • Overloading an operator cannot change its precedence. • Overloading an operator cannot change its associativity. • Overloading an operator cannot change its "arity" (i.e. number of operands) • It is not possible to create new operators -- only new versions of existing ones. • Operator meaning on the built-in types cannot be changed.
Operator Overloading Rules • Some operators can be written as member functions of a class • Some operators can be written as stand-alone functions -- it's common to use friend on these • Some operators can be written either way (your choice) • A binary operator has two operands • Written as a stand-alone function, both operands would be sent as parameters, so it would be a function with two parameters • Written as a member function, the first operand would be the calling object, and the other would be sent as a parameter (i.e. a function with one parameter) • A unary operator has one operand • As a stand-alone function, the operand is sent as a parameter • As a member function, one calling object, no parameters
Operator Overloading Format • An operator is just a function. This means that it must be created with a return type, a name, and a parameter list The rules above give some restrictions on the parameter list • The name of an operator is always a conjunction of the keyword operator and the operator symbol itself. • Examples: operator+ operator++ operator<< operator==
Operator Overloading Format • So the format of an operator overload declaration is just like that of a function, with the keyword operator as part of the name: returnTypeoperatorOperatorSymbol (parameterList);
Operator Overloading Example • Consider the arithmetic operators. intx = 3, y = 6, z; float a = 3.4, b = 2.1, c; z = x + y; c = a / b; • Now consider this notation. 1/2 + 1/3 // evaluates to 5/6 2/3 - 1/3 // evaluates to 1/3
Operator Overloading Example • Now, what about using arithmetic operators on our Fraction class (a user-defined type): Fraction n1, n2, n3; n3 = n1 + n2; // will the compiler accept this? • It should be clear that this would not make sense to the compiler. Fraction is a programmer-defined type. How would the computer know about common denominators, etc? • These code statements would be nice to use, however, because it's the same way we use other numeric types (like int and double). • Operator overloading makes this possible
Arithmetic Operator Overloading • The arithmetic operators can be overloaded either as: • stand-alone functions or • member functions.
Stand-alone Arithmetic Operator Overloading • To add objects, we could write a function called Add, of course. Recall this example: friend Fraction Add(Fraction f1, Fraction f2); • With this function prototype, a sample call would be: Fraction n1, n2, n3; n3 = Add(n1, n2);
Stand-alone Arithmetic Operator Overloading • The + notation would certainly be more convenient. • The operator version just has a different name: friend Fraction operator+(Fraction f1, Fraction f2); • The usual function style call would look like this: n3 = operator+(n1, n2); • While this is legal, the advantage is being able to use the more common infix notation: n3 = n1 + n2; // this becomes legal
Stand-alone Arithmetic Operator Overloading • Here's a full definition of the + operator for class Fraction. Note that this is also a possible definition for the Add function: Fraction operator+(Fraction f1, Fraction f2) { Fraction r; // declare a Fraction for result // load result Fraction with sum numerators r.numerator= (f1.numerator*f2.denominator) + (f2.numerator*f1.denominator); // load result with the common denominator r.denominator= f1.denominator * f2.denominator; return r; // return the result Fraction }
Stand-alone Arithmetic Operator Overloading • Once this operator overload is defined, then the following is legal. • Note that cascading also works (because the operation returns a Fraction). Now we have the standard intuitive use of + Fraction n1, n2, n3, n4, n5; n5 = n1 + n2 + n3 + n4; // now it is legal! • Note: This function could also be written with const reference parameters friend Fraction operator+(const Fraction& f1, constFraction& f2);
Member Function Arithmetic Operator Overloading • One member function version of Add was: Fraction Add(const Fraction& f) const; • A sample call to this function: Fraction n1, n2, n3; n3 = n1.Add(n2);
Member Function Arithmetic Operator Overloading • The corresponding operator overload. Again, we change the name to operator+ Fraction operator+(const Fraction& f) const; • Again, we could use typical function notation, and the dot-operator: n3 = n1.operator+(n2); • But the whole point is to be able to use the more familiar notation, which still works, and no dot-operator required: n3 = n1 + n2; // n1 is calling object, n2 is argument
Member Function Arithmetic Operator Overloading • A full definition of this version of operator+ Fraction Fraction::operator+(const Fraction& f2) const { Fraction r; // result r.numerator= (numerator * f2.denominator) + (f2.numerator * denominator); r.denominator= (denominator * f2.denominator); return r; }
Increment (++) / Decrement (--) Operators • There are two versions of ++, pre-increment and post-increment • The pre-increment operator: Has one operand, which can be the calling object (member function) or a parameter (for non-member function implementation) • Performs the increment, then returns the newly incremented object. • The post-increment operator: Has one operand, officially. But to distinguish it from the pre-increment, an extra dummy parameter (int) is included. • Performs the increment, but returns a copy of the object's previous value.
Operator += • operator+= It is a binary operator. In this example, it's written as a member function, so it has one parameter. • The second parameter is "added" to the calling object. Note that this is a shortcut assignment, so the left side (the calling object) is changed. The right side (the parameter) is not changed -- hence the parameter is passed as a const reference • Note that the function returns *this. The keyword this is a pointer to the calling object (from inside a member funtion). So *this is the target -- i.e. the calling object itself • Note that the return from this operator is an IntPair object, returned by reference.
More examples • IntPair class • IntPair v2 • Version 2 uses the +=