Operator overloading. Operatorsand precedence zLeft to right associative y:: scope resolution y. direct member access y-> indirect member access y[] subscripting.

Presentation on theme: "Operator overloading. Operatorsand precedence zLeft to right associative y:: scope resolution y. direct member access y-> indirect member access y[] subscripting."— Presentation transcript:

Operatorsand precedence zLeft to right associative y:: scope resolution y. direct member access y-> indirect member access y[] subscripting y() function call y() function-style cast y++ postfix increment y-- postfix decrement Level 17 Level 16

Operators zRight to left associative y++ prefix increment y-- prefix decrement y~ one’s complement y! not y- unary minus y+ unary plus y& address of y* de-reference ynew allocate a single instance ynew[] allocate array of instances ydelete delete single instance ydelete[] delete multiple instances y() C-style cast Level 15 Level 14

Operators zLeft to right associative y* multiplication y/ division y% modulus y+ addition y- subtraction y<< shift left y>> shift right y< less than y<= less than or equal to y> greater than y>= greater than or equal to Level 13 Level 12 Level 11 Level 10

Operators zLeft to right associative y== equal to y!= not equal y& bitwise and y^ bitwise exclusive or y| bitwise inclusive or y&& logical and y|| logical or y?: conditional expression Level 9 Level 4 Level 8 Level 7 Level 6 Level 5 Level 3

Operators zRight to left associative y= assignment y*= multiply and assign y/= divide and assign y%= modulus and assign y+= addition and assign y-= subtract and assign y<<= shift left and assign y>>= shift right and assign y&= bitwise AND and assign y|= bitwise OR and assign y^= exclusive OR and assign y, comma (left to right) Level 2 Level 1

Rule of Big Three zIf a class has any of ycopy constructor ydestructor yassignment operator zIt needs all three zDestructor usually shows up first zException: when destructor only decrements number of instances

Function overloading zOperators are really functions zThey have arguments zThey return values zThe only difference is that their names take on a specific form: yoperator+ yoperator[] yetc.

Function overloading (con’t) zAn overloaded function is one which has the same name but several different forms. zFor example, we overloaded the constructor for the Date class ydefault Date d; yinitializing Date d(9,22,99); ycopy Date d1(d); yother Date d(“Sept.,22,1999);

Operator overloading zJust as there may be many versions of a function due to overloading, there may be many versions of operators. zExample: operator/ ya = 14.0 / 2; (one float and one int argument) ya = 14.0 / 2.0; (two float arguments) ya = 14 / 2; (two ints, INTEGER DIVISION) zMany operators are already overloaded for us to handle a variety of argument types.

Operator Overloading zThe operator “+” also has different semantics depending on the type of its “arguments” zExample int i, j; double d, e; i + j; /* add two int */ i + d; /* add an int and a double */

Operator overloading zWe want user-defined types to behave like built-in types class complex { /* … */ }; complex a(2,1), b(3,0); … cout << a + b << a*b << -b; cout << (a != b);

More examples of operator overloading Vector v1, v2; v2 = v1; // overloaded assignment cin >> v1 >> v2; // overloaded >> cout << v1[5] << v2++; // overloaded <<, [], ++ Vector v3; v3 += (v1 - v2); // overloaded +=, -

Advantages of operator overloading zUser-defined types behave like built-in types yfamiliar notation (infix notation for binary ops) zAlternative to operator overloading yPostfix notation for unary operators: v1.incr(1).add(v2).print(); yPrefix notation for binary operators (Lisp-like) equal(v1, plus(v2, v3)); yVerbose and inconsistent

Extended example zEmployee class and objects class Employee { private: int idNum; double salary; public: Employee(const int id, const double salary); double addTwo(const Employee& emp); double operator+(const Employee& emp); double getSalary() { return salary; } }

The member functions ‘addTwo’ and operator+ double Employee::addTwo(const Employee& emp) { double total; total = salary + emp.getSalary(); return(total); } double Employee::operator+(const Employee& emp) { double total; total = salary + emp.getSalary(); return(total); }

Using the member functions double sum // these three statements do the same thing sum = Clerk.addTwo(Driver); sum = Clerk.operator+(Driver); sum = Clerk + Driver; // the syntax for the last one is the most natural // and is easy to remember because it is consistent // with how the + operator works for everything else

Operator Overloading: Restrictions zPrecedence and associativity cannot be changed zSome operators cannot be overloaded: yScope resolution :: yMember access. and.* yTernary conditional expression ?:

Implementing overloaded operators zThe compiler uses the types of arguments to choose the appropriate overloading. Vector v1, v2; v1 + v2; // “Vector” + string s1, s2; s1 + s2; // string “+” zOverloaded operators can be yclass methods ynon-class functions

Definining overloaded operators complex operator+( const complex& a, const complex& b);  keyword operator followed by operator symbol

Member vs. Nonmember functions zOperators may be either nonstatic members of a class or nonmembers. zWe will only use operators that are member functions. zIn fact, many operators MUST be member functions: =, (), [], ->

Example zThe fraction class. zFractions consist of numerators and denominators. zIn addition, we might want to include data members to store a symbol (/), and perhaps even store the decimal equivalent of the fraction as a double.

The fraction class Class Fraction { private: static char symbol; int numerator; double floatingPoint; int denominator; double convert(); public: Fraction(const int n=0, const int d=1); Fraction(const int w, const int n, const int d); void setData(const int n, const int d); void showData(); void invertFraction(); int greatestCommon Denom(); void reduceFraction(); Fraction operator+(Fraction& f2); }

Overloaded operator+ Fraction Fraction::operator+(Fraction& f2) { Fraction result; int tempNum, tempDenom; tempNum = Fraction::numerator * f2.denominator + f2.numerator * Fraction::denominator; tempDenom = Fraction::denominator * f2.denominator; result.setData(tempNum, tempDenom); result.reduceFraction(); return(result); }

Client code (main program) #include “fraction.cpp” void main() { Fraction firstFrac(1,8), secondFrac(2,7), sum; sum = firstFrac + secondFrac; sum.showData(); } RESULT: Decimal is 0.410714 Fraction is 23/56

Overloaded operator- Fraction Fraction::operator-(Fraction& f2) { Fraction result; int tempNum, tempDenom; tempNum = Fraction::numerator * f2.denominator - f2.numerator * Fraction::denominator; tempDenom = Fraction::denominator * f2.denominator; result.setData(tempNum, tempDenom); result.reduceFraction(); return(result); }

Overloaded operator+ Fraction Fraction::operator*(Fraction& f2) { Fraction result; int tempNum, tempDenom; tempNum = Fraction::numerator * f2.numerator; tempDenom = Fraction::denominator * f2.denominator; result.setData(tempNum, tempDenom); result.reduceFraction(); return(result); }

Overloaded operator/ Fraction Fraction::operator/(Fraction& f2) { Fraction result; int tempNum, tempDenom; tempNum = Fraction::numerator * f2.denominator; tempDenom = Fraction::denominator * f2.denominator; result.setData(tempNum, tempDenom); result.reduceFraction(); return(result); }

Overloaded operators as class methods zAll (non-static) methods have an implicit arg Class* this zSo, unary operators that are class methods do not take any arguments zand binary operators that are class methods may need only one argument.

“this” pointer zEvery class has a built-in pointer “this” to the object on which a method was called zIt is available only inside methods zused for self-referencing:  this->month = month;  this is typed!  Class* const for methods of objects Class  const Class* const for const methods

Old version of operator+ Fraction Fraction::operator+(Fraction& f2) { Fraction result; int tempNum, tempDenom; tempNum = Fraction::numerator * f2.denominator + f2.numerator * Fraction::denominator; tempDenom = Fraction::denominator * f2.denominator; result.setData(tempNum, tempDenom); result.reduceFraction(); return(result); }

New version of operator+ using ‘this’ Fraction Fraction::operator+(Fraction& f2) { this->numerator = this->numerator * f2.denominator + f2.numerator * this->denominator; this->denominator = this->denominator * f2.denominator; this->setData(tempNum, tempDenom); this->reduceFraction(); return(*this); }

Multiple operators zOften, you may need to reference an operator more than once in a expression. zExample: ytotal = a + b + c; zBut this can cause big problems when operator overloading is involved zSee next few slides for an example

Client code for class Employee Void main() { Employee Clerk(115, 20000.00); Employee Driver(256, 15500.55); Employee Secretary(567, 34200.00); double sum; sum = Clerk + Driver + Secretary; cout << “Sum is “ << sum; }

The problem zOperator + is left to right associative, so Clerk and Driver are added. The result is a double. zNow that double is on the left and an Employee is on the right (Secretary) zBUT THE OPERATOR + is only defined for arguments of type Employee, not zoperator+(double, Employee&)

The problem gets worse zIt would seem that all we have to do is write another version of the overloaded operator to work with the arguments (double, Employee&) zBut… yalthough we could overload an operator to work like this: ysum = Secretary + num; zWe cannot overload one like this: ysum = num + Secretary; // why not?

The answer zWe cannot overload + for a double zDouble is a native type, and it is also the implicit type in this version of our function! zThe real solution is to make sure that your operator+ function never returns a double (or any other native type). zAn operator to add Employees should return an Employee (see next slide)

Solution example Employee Employee::operator+(const Employee& emp) { Employee total(999,0); // dummy values total.salary = this->salary + emp.salary; return(total); }

Final note zIt is important that the operator+ function return an Employee object rather than a reference to an Employee object. zIf it returns a pointer to total then the returned pointer would pass out of scope and cease to exist.

Download ppt "Operator overloading. Operatorsand precedence zLeft to right associative y:: scope resolution y. direct member access y-> indirect member access y[] subscripting."

Similar presentations