1 / 22

Recitation Week 6

Recitation Week 6. Object Oriented Programming COP3330 / CGS5409. Today’s Recitation. Comparison Operator Overloading Insertion (<<)/Extraction (>>) Operator Overloading Dynamic Memory Allocation. Overloading Comparison Operators. The comparison operators can also be overloaded

Download Presentation

Recitation Week 6

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Recitation Week 6 Object Oriented Programming COP3330 / CGS5409

  2. Today’s Recitation • Comparison Operator Overloading • Insertion (<<)/Extraction (>>) Operator Overloading • Dynamic Memory Allocation

  3. Overloading Comparison Operators • The comparison operators can also be overloaded • stand-alone functions or • member functions • Consider the Equals function example: friend bool Equals(const Fraction& f1, const Fraction& f2); • We can easily write this as an operator overload: friend bool operator== (const Fraction& f1, constFraction& f2);

  4. Overloading Comparison Operators • Here are corresponding sample calls: Fraction n1, n2; if (Equals(n1, n2)) cout<< "n1 and n2 are equal"; • Contrast with this: Fraction n1, n2; if (n1 == n2) cout<< "n1 and n2 are equal";

  5. Overloading the Insertion << and extraction >> Operators • As with other operators, the << and >> operators are defined for the basic types. • If you build your own class, don't expect << to automatically work with your new types of objects! • If you want it to work, you have to teach the computer how to do such output. Consider the following: Fraction f; cout<< f; // how would the machine // know how to do this?

  6. Overloading the Insertion << and extraction >> Operators • The insertion operator << is only pre-defined for built-in types.  • The iostream.h library doesn't know about the Fraction type. • The << operator is a binary operator (2 parameters, left side and right side).  • The first parameter is always an ostream object (we've mostly used cout, so far).  Because of this, it cannot be defined as a member function (it would have to be a member of the ostream class, which we cannot change).  • The << and >> operators should always be defined as outside functions (usually friend functions).  • The second parameter is whatever new type it is being overloaded to print: friend ostream& operator << (ostream& s, Fraction f);

  7. Overloading the Insertion << and extraction >> Operators friend ostream& operator << (ostream& s, Fraction f); • This declaration has all of the usual parts for defining a function.  • The name is operator<< (the keyword operator and the operator symbol). • The return type is ostream&. • The parameters are (ostream& s, Fraction f). When defining overloads of << and >> , always pass the stream parameters by reference.

  8. Overloading the Insertion << and extraction >> Operators • A better way to write this operator is: friend ostream& operator << (ostream& s, const Fraction& f); • Notice that the first one passes the Fraction by value (and makes a copy). • The second passes by reference (avoiding the overhead of a copy). • It is declared as a const because the Fraction does not need to change if we are just doing output.

  9. Overloading the Insertion << and extraction >> Operators • Here is the corresponding prototype for extraction >> friend istream& operator >> (istream& s, Fraction& f); • Notice that the Fraction parameter for >> is also a reference parameter.  • This is because we are getting input into the object, so we need to work on the original, not a copy.

  10. Overloading the Insertion << and extraction >> Operators • Remember the Show() function of the Fraction class: void Fraction::Show() { cout<< numerator << '/' << denominator; } • Here is how the << operator might be defined for Fraction.  Notice how similar it is to the Show() function. ostream& operator << (ostream& s, const Fraction& f) { s << f.numerator << '/' << f.denominator; return s; }

  11. Overloading the Insertion << and extraction >> Operators • Note the differences between this and the Show() function. • In the new function, we must have a return statement, because we have a return type (as opposed to "void" in the original Show function). We return the ostream itself. • Note also that we must use "s" (not "cout") in the function body.  This is the formal parameter, and a nickname for whatever was passed in (which could be cout, but also could be a different ostream). • Last, notice that this is not a member function of the Fraction class, but rather, a friend function.  So, we can access the private data, but we must do it through the object

  12. Overloading the Insertion << and extraction >> Operators • Once this is defined, we can use a Fraction object in a cout statement: Fraction f1; • So now, instead of: cout<< "Fraction f1 is "; f1.Show(); cout<< '\n'; • We can write: cout<< "Fraction f1 is " << f1 << '\n';

  13. Memory Allocation Types • Remember that memory allocation comes in two varieties: • Static (compile time): Sizes and types of memory (including arrays) must be known at compile time, allocated space given variable names, etc. • Dynamic (run-time): Memory allocated at run time. Exact sizes (like the size of an array) can be variable. Dynamic memory doesn't have a name (names known by compiler), so pointers used to link to this memory

  14. Dynamic Allocation & Cleanup • Allocate dynamic space with operator new, which returns address of the allocated item. Store in a pointer: int* ptr = new int; // one dynamic integer double * nums = new double[size]; // array of doubles, called "nums" • Clean up memory with operator delete. Apply to the pointer. Use delete [] form for arrays: delete ptr; // deallocates the integer above delete [] nums; // deallocatesdouble array above

  15. Accessing Dynamic Items • Remember that to access a single dynamic item, dereference is needed: cout<< ptr; // prints pointer contents cout<< *ptr; // prints the target • For a dynamically created array, the pointer attaches to the starting position of the array, so can act as the array name: nums[5] = 10.6; cout<< nums[3];

  16. Dynamic Allocation of Objects • Just like basic types, objects can be allocated dynamically. • When an object is created, the constructor runs. Default constructor is invoked unless parameters are added: Fraction * fp1, * fp2, * flist; fp1 = new Fraction; // uses default // constructor fp2 = new Fraction(3,5); // uses constructor with // two parameters flist= new Fraction[20]; // dynamic array of 20 // Fraction objects • Default constructor used on each

  17. Dynamic Object De-allocation • Just like basic types, dynamically created objects must also be de-allocated. • De-allocation with delete works the same as for basic types: delete fp1; delete fp2; delete [] flist;

  18. Dot-Operator vs. Arrow-Operator • Dot-operator requires an object name (or effective name) on the left side objectName.memberName // member can be data or function • The arrow operator works similarly as with structures. pointerToObject->memberName

  19. Dot-Operator vs. Arrow-Operator • Remember that if you have a pointer to an object, the pointer name would have to be dereferenced first, to use the dot-operator: (*fp1).Show(); • Arrow operator is a nice shortcut, avoiding the use or parentheses to force order of operations: fp1->Show(); //equivalent to (*fp1).Show();

  20. Dynamically Allocated Objects • When using dynamic allocation of objects, we use pointers, both to single object and to arrays of objects. Here's a good rule of thumb: • For pointers to single objects, arrow operator is easiest: fp1->Show(); fp2->GetNumerator(); fp2->Input();

  21. Dynamically Allocated Arrays • For dynamically allocated arrays of objects, the pointer acts as the array name, but the object "names" can be reached with the bracket operator. Arrow operator usually not needed: flist[3].Show(); flist[5].GetNumerator(); • Note that this would be INCORRECT, flist[2] is an object, not a pointer! flist[2]->Show();

  22. Questions?

More Related