CS105 C++ Lecture 7 More on Classes, Inheritance "
Operator Overloading Global vs Member Functions Difference: member functions already have this as an argument implicitly, global has to take another parameter. () [] -> or assignment has to be member function Leftmost operand For member function: must be object (or reference to object) of operator s class. Global function used when it is not user-defined object (overloading << and >> require left operand to be ostream& and istream&) Global operators can be made friend of class if needed. Global functions enable commutative operations 2
Overloading Restrictions To use an operator with class, operator must be overloaded with 3 exceptions (but these can be overloaded too): Assignment (=) does member-wise assignment for objects. (overload for classes with pointer members) The & and, operators may be used with objects without overloading The following cannot be changed for operators: Precedence (order of operations) Associativity (left-to-right or right-to-left) Arity (how many operands) Can t overload:..* ::?: 3
Overloaded Function Call Operator Use ( ) operator string operator( )( int index, int sublength ) const; Returns a substring for class String starting at index, of length sublength string s1( Hello ); cout << s1(1,3) << endl; 4
Operators: Converting between Types Conversion constructor is a single-argument constructor that turns objects of other types (including fundamental types) into objects of a particular class. EX: Date::Date(string datestr); Conversion/cast operator converts object into object of another class or to a fundamental type Date::operator char *( ) const; /*convert Date object into char*. const above means does not modify original object */ Date myd; static_cast<char *>(myd); //CALLS myd.operator char* () Conversion functions can be called implicitly by the compiler 5
Why References, Why Pointers? References invoke functions implicitly, like copy constructor, assignment operator, other overloaded operators Can pass large objects without passing address Don t have to use pointer semantics Pointers Good for dynamic memory management Ease of pointer arithmetic Provides level of indirection in memory 6
Some Details Date mydate = olddate; //olddate of type Date //Does this call copy constructor or operator=? Difference between copy constructor and assignment operator? const Array &Array::operator=(const Array &right); When we have dynamically allocated data members Define destructor Define copy constructor Define = (assignment operator) [All of above have defaults provided by compiler] 7
Valgrind Debugger especially good for checking for memory leaks Put -g in your g++ line To use: valgrind <options> program Options: --leak-check=full --show-reachable=yes www.valgrind.org 8
Valgrind Output ==21657== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 1) ==21657== malloc/free: in use at exit: 42 bytes in 6 blocks. ==21657== malloc/free: 49 allocs, 43 frees, 788 bytes allocated. ==21657== For counts of detected errors, rerun with: -v ==21657== searching for pointers to 6 not-freed blocks. ==21657== checked 108,732 bytes. ==21657== ==21657== 42 bytes in 6 blocks are definitely lost in loss record 1 of 1 ==21657== at 0x4022ED4: operator new[](unsigned int) (vg_replace_malloc.c:268) ==21657== by 0x8049E57: main (in file) ==21657== ==21657== LEAK SUMMARY: ==21657== definitely lost: 42 bytes in 6 blocks. ==21657== possibly lost: 0 bytes in 0 blocks. ==21657== still reachable: 0 bytes in 0 blocks. ==21657== suppressed: 0 bytes in 0 blocks. 9
Inheritance Software reuse inherit a class s data and behaviors and enhance with new capabilities. Existing class = base class, inheriting class = derived class (no super/ subclass like Java) Derived class is more specialized than base class. Object instances of derived class are also object of base class (All cars are vehicles, but not all vehicles are cars.) There can be multiple levels of inheritance. 10
Inheritance Details class Circle : public Shape What is base, what is derived here? Default = public inheritance (base member variables retain same access level in derived class), but there are other types Friends are not inherited When redefine something in derived class, use <baseclassname>::member to access base class s version. 11
Inheritance and Member Variables Derived class has all attributes of base class. Derived class can access non-private members of base class. protected members of base class are accessible to members and friends of any derived classes. Derived does not inherit constructor or destructor of base. Derived class can re-define base-class member functions for its own purposes, customizing base class behaviors. Size of derived class = non-static data members of derived class + non-static data members of base class (even if private) 12
Base Class Example class Member { public: Member(string name); Member( Member const &); Member& operator= (Member const &); ~Member(); string getname() const; void setname(string name); void print() const; private: string myname; }; 13
Derived Class Example #include Member.h class Employee : public Member { public: Employee(string name, double money); Employee( Employee const &); Employee& operator= (Employee const &); ~Employee (); double getsalary() const; void setsalary(double money); void print() const; private: double salary; }; 14
Employee Constructor #include Employee.h Employee::Employee( string name, double money ) : Member(name) //base class initializer syntax { salary = money; } C++ requires derived class constructor to call base class constructor to initialize inherited base class data members (if not explicit, default constructor would be called). 15
Employee s print Function void Employee::print() const { cout << Employee: ; Member::print(); //prints name from base class cout << \nsalary: << getsalary() << endl; } 16
Constructor/Destructor Order When we instantiate a derived class: 1. Base class s member object constructors execute (if they exist) 2. Base class constructor executes 3. Derived class s member object constructors execute 4. Derived class constructor executes Destructors called in reverse order. Base class constructors, destructors and overloaded assignment operators are not inherited by derived classes. However derived class can call base class s version of these. 17
Encapsulation Given a derived class can directly access and modify protected data members of base class, should base class member variables be protected? Or private? 18
Encapsulation Given a derived class can directly access and modify protected data members of base class, should base class member variables be protected? Or private? + No overhead of function call in derived class Direct modification does not allow for error checking. If base class member variables names change, we have to change all derived classes use of them. 19
Kinds of Inheritance Base Class Access (down) Public inheritance Protected inheritance Private inheritance public public protected private protected protected protected private private private private private 20
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. cout << mptr->getname(); //what does this print? 7. mptr->print(); //and this? 21
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. cout << mptr->getname(); //Jill 7. mptr->print(); //Jill 22
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. Employee *eptr = &e1; 7. cout << eptr->getname() << eptr->getsalary(); //result? 8. eptr->print(); //what function does this call? 23
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. Employee *eptr = &e1; 7. cout << eptr->getname() << eptr->getsalary(); //Jack 65000 8. eptr->print(); //Employee.print which calls Member.print 24
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. Employee *eptr = &e1; 7. mptr = &e1; //is this ok? Base class pointer to derived class? 25
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. Employee *eptr = &e1; 7. mptr = &e1; //Yes, valid; all Employees are Members 8. eptr = &m1; //this valid? Derived class pointer to base class? 26
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. Employee *eptr = &e1; 7. mptr = &e1; //Yes, valid; all Employees are Members 8. eptr = &m1; //No, not all Members are Employees; //compiler error 27
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. mptr = &e1; //yes, this is valid; all Employees are Members 7. cout << mptr->getname(); //what does this print? 8. cout << mptr->getsalary(); //this ok? 9. mptr->print(); //what function does this call? 28
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. mptr = &e1; 7. cout << mptr->getname(); //Jack 8. cout << mptr->getsalary(); //compiler error 9. mptr->print(); //calls Member s print: Jack 29
Polymorphism Member *mptr = &e1; mptr->print(); Method that is called depends on the type of the handle, not the type of the object Polymorphism enables the compiler to call the more specific method, i.e. call based on the type of object dynamically. Because all derived class objects ARE base class objects, 1 base class pointer can enable calls to any number of derived class methods. 30
Polymorphism! Polymorphism enables processing of classes that are part of the same hierarchy as if they were all objects of base class. Program in the general rather than in the specific Linked concepts Virtual functions Dynamic binding Dynamic casting Runtime type information (RTTI) 31
Polymorphism! Member *mptr = &e1; mptr->print(); To get the Employee print function to be called, it has to be declared virtual (in the.h) For virtual functions, the type of the object being pointed to determines function call, not type of handle. Choosing right function to call is at execution time (not compile time), so it is done dynamically. This is called dynamic binding 32
Polymorphism! Member *mptr = &e1; mptr->print(); Dynamic binding with virtual functions only works with pointer and reference handles. Member m1( Jill ); m1.print(); resolved at compile time => static binding! Base class declares functions as virtual, and implicitly for all derived classes that function is virtual (whether declared thus or not virtuality is inherited). Derived class virtual function can override base class function (if not virtual, function redefined in derived class), or takes on base class s implementation if not defined in derived class 33
Base Class Example class Member { public: Member(string name); Member( Member const &); Member& operator= (Member const &); ~Member(); string getname() const; void setname(string name); virtual void print() const; private: string myname; }; 34
Derived Class Example #include Member.h class Employee : public Member { public: Employee(string name, double money); Employee( Employee const &); Employee& operator= (Employee const &); ~Employee (); double getsalary() const; void setsalary(double money); virtual void print() const; //keywork here unnecessary, but good practice. private: double salary; }; 35
Instantiating Objects Example 1. #include Member.h 2. #include Employee.h 3. Member m1( Jill ); 4. Employee e1( Jack, 65000); 5. Member *mptr = &m1; 6. mptr = &e1; 7. cout << mptr->getname(); //Jack 8. mptr->print(); //calls Employee s print: Jack 65000 36
Kinds of Assignments Base class pointer -> base class object = FINE Invokes base class functionality Derived class pointer -> derived class object = FINE Invokes derived class functionality Base class pointer to derived class object = FINE Will invoke base class functionality unless functions declared virtual, then will invoke derived class functionality Derived class pointer to base class object = COMPILER ERROR (unless explicit cast) 37
Base class is a Derived class? Derived class pointer -> base class object Could downcast? DANGEROUS! Member *mptr; Employee *eptr = static_cast< Employee* > (mptr); eptr->getsalary(); 38