Presentation is loading. Please wait.

Presentation is loading. Please wait.

The dirty secrets of objects

Similar presentations


Presentation on theme: "The dirty secrets of objects"— Presentation transcript:

1 The dirty secrets of objects
Object assignment: consider the class class Student{ int age; std::string name; } Consider now the following code: Student s1; s1.age = 21; s1.name = “Bob”; Student s2; s2.age = 20; s2.name = “Alice”; s1 = s2; // wtf does this actually do??

2 Object assignment By default, when one object is assigned to another, all matching attributes are copied directly (hooray!) Called member-wise assignment In the Student example, the data will get copied as we expect What about assignment of the following class? class Student{ int age; std::string name; int numberOfScores; int* scores; // points to an array! }

3 Object Assignment If an object has a pointer which, potentially, points to extra data, only the value of the pointer is copied into the new object The data pointed to is not copied For the student data above: S2 Scores*: 0x0fe2ab S1 Scores*: 0x0fe2ab 35 79 99 95

4 The “Fix” The copy constructor is a special constructor which takes the form: ClassName::ClassName(ClassName& old); Called when an object is initialized as ClassName newObj = oldObj; Or ClassName newObj(oldObj); Note the reference parameter! The purpose is to allow more detailed copying of member objects inside the copied object: For our student class, we would have to allocate a new array of the same length and copy over each element (which we know how to do easily!) Good idea: add the “const” modifier to the copied object argument

5 The Rule OF Three If you need to define any of the following, you need to define all three: Destructor Copy constructor Copy assignment operator

6 More “what if” What if the two objects are already initialized and then one is assigned to the other? Student s1, s2; s2 = s1; // Constructor doesn’t get called because we’re not initializing  We need to override the assignment operator itself

7 Operator Overloading We want to be able to mimic the copy constructor behavior in regular assignment We want to be able to compare different objects directly payroll1 > payroll2 payroll1 == payroll2 We want to print objects directly cout << payroll1 << endl;

8 Operator overloading In C++, every operator is really just a shortcut for a special function Assignment (=): Void operator=(const TypeName &operand) (doesn’t have to be void) (doesn’t have to pass by reference) (doesn’t have to have a const parameter, but semantically safer!) Comparison (>): Bool operator>(const TypeName operand) Etc.

9 Operator Overloading Can overload:
If you forget: Or:

10 Operator Overloading Cannot overload:

11 Assignment Operator Semantics: “x = y” means “copy y into x”
Prototype: Class& operator=(const Class& other) Note the return type: used to allow statements such as “a = b = c” Caveats If any dynamic memory is used, need to free it before copying “standard” C++ requires the assignment to take no action on self assignment (i.e. “a = a”) For instance, we could encounter very bad memory leaks! So we must add a check to skip unnecessary work

12 Array Index Operator Overload
Prototype: ReturnType& ClassName::operator[](IndexType b); Useful for lists, but have to handle out-of-bounds via exceptions or other error handling Can overload for specific object parameters, for more semantic indexing

13 Arithmetic Overload ReturnClass MemberClass::operator+(ArgClass b);
Example: a “Time” class with ”hours” and “minutes” members Need to make arithmetic modular (mod 12) and (mod 60), respectively Note: these ones don’t modify the operands, but rather return a third, temporary object representing the value of the expression! Good idea to make things const!

14 Mixing Types Suppose for a “Time” object, we want to just be able to type, for example: Time a(2, 15); Time b = a + 1; // is obviously ambiguous but also, does not match our overloaded +  Solution: use friends to overload the operator outside the class! Prototype: friend Time operator+(Time t, int h); Will also need the reverse if we want it to be commutative Can use the first one

15 Stream Overload Will again, need to define outside the class of the type we want to use with the stream operator Why? We’re really overloading a function defined in std std::ostream& operator<<(std::ostream& os, const T& obj) std::istream& operator>>(std::istream& is, T& obj) As before, will sometimes need to be friends of the class, unless we have getters for all the relevant data

16 Object Conversion We can “covert” complicated objects into others in the same way that ints can be automatically converted to doubles: Int a = 10 Double b = a; What actually happens is that “a” is first converted to a double, then the assignment is performed Since this is a pre-defined conversion, we can define our own conversion functions! operator TypeName(){ … } No return type Can even define for non-fundamental types (e.g. other classes)

17 Friends of Classes We can specify that functions (or entire classes) are allowed to access private members of a certain class Syntax: friend ReturnType FunctionName (ParameterTypeList) Can also declare entire classes a friend, but isn’t generally useful, since it allows access to any member functions of the friend, even ones added later Better off just combining the classes

18 Friend Example Possible situation: we have several classes for various objects (e.g. Students, Courses, Instructors) along with their classes However, because we like separation of concerns, none of them have any user-input build-in or any output If we set up a database class, which combines these objects, we can declare some input/output methods within the database To make it easier (not dealing with getters/setters or more complex members), we can choose the input/output specific methods inside the database class to be a friend of each of the objects in the database (Student, Course, Instructor)

19 Friend Example Recall from lab: PayRoll and PayRollQueue
The PayRoll class could have “friended” the enqueue or dequeue functions of the queue, just in case we needed to access the private members class PayRoll{ friend void PayRollQueue::enqueue(PayRoll p); // could now access p.name, etc. }


Download ppt "The dirty secrets of objects"

Similar presentations


Ads by Google