OOP Etgar 2008 – Recitation 61 Object Oriented Programming Etgar 2008 Recitation 6
OOP Etgar 2008 – Recitation 62 Inheritance Basis of Object-Oriented Programming
OOP Etgar 2008 – Recitation 63 Where It Comes From? As we try to model the “real world” in C++, we run into the need to model hierarchical relationships between classes – to express commonality. A Student and a Teacher have something in common – they are both Persons. This means that whenever we need a Person, we can use either Student or a Teacher.
OOP Etgar 2008 – Recitation 64 Terminology The mechanism that allows this in C++ is called inheritance. We say that –Student inherits from Person. –Person is a base class and Student is a derived class. –Person is a superclass and Student is a subclass. The public inheritance models the is-a relationship.
OOP Etgar 2008 – Recitation 65 What Does It Mean? Any place a base can be used, a derived can be used. A derived inherits base’s methods and data members (but not all). In practice, a derived class extends the base class, or specializes it. –A Student can do anything a Person can and more. –A Person is more general than a Student. Student is-a kind of Person.
OOP Etgar 2008 – Recitation 66 Syntax class B { public: … protected: … private: … }; class D : public B { public: … private: … };
OOP Etgar 2008 – Recitation 67 Syntax Explained The syntax for saying that D inherits from B is: : public B before class’s opening brace. The public keyword is essential (this is called public inheritance). protected: is a new access level – anything in the protected zone can be accessed by the derived classes only.
OOP Etgar 2008 – Recitation 68 Access Levels The base class is “embedded” in the derived class. Derived uses public and protected members of base like they were his own. Derived contains private members of base, but can’t access them. Clients of derived class can use public members from base and derived like they were all defined public in derived.
OOP Etgar 2008 – Recitation 69 Acess Levels Summary An object of class D “exposes to the world” –Everything declared public in D. –Everything declared public in B. An object of class D can access: –Everything declared public, protected or private in class D. –Everything declared public or protected in class B. An object of class D contains: –Everything declared public, protected or private in class D or in class B.
OOP Etgar 2008 – Recitation 610 Student s and Person s class Person { public: void print_name(); protected: string get_name(); private: string _name; }; class Student : public Person { public: void print_univ(); private: string _univ; };
OOP Etgar 2008 – Recitation 611 Their Use int main() { Student s; s.print_name();// Prints the name s.print_univ();// Prints the university cout << s._univ;// Can't access cout << s._name;// Can't access cout << s._get_name();// Can't access }
OOP Etgar 2008 – Recitation 612 Their Implementation void Student::print_univ() { cout << _univ;// Student's member cout << _name;// Can't access cout << get_name();// Inherited protected member } void Person::print_name() { cout << _name; }
OOP Etgar 2008 – Recitation 613 Class Hierarchy Base doesn’t know about derived classes. Person should not “think about” Student in particular BUT Person should “think about” things common to all derived classes.
OOP Etgar 2008 – Recitation 614 The (Limited) Benefit void introduce(Person p) { cout << "Hello, my name is "; p.print_name(); } int main() { Person p; Student s; introduce(p); introduce(s); return 0; }
OOP Etgar 2008 – Recitation 615 Constructing and Assigning Derived Classes
OOP Etgar 2008 – Recitation 616 Constructors and Inheritance An object of a derived class “includes” members of the base class. When constructing an object all members should be initialized. Therefore derived’s constructors needs to make sure the members inherited from base are initialized correctly. It does it by “calling” base’s constructor.
OOP Etgar 2008 – Recitation 617 Example Person::Person(string iname) : _name(iname) {} Student::Student(string i_name, string i_univ) : Person(i_name), _univ(i_univ) {}
OOP Etgar 2008 – Recitation 618 Construction Order Note the derived’s construction order: –First all base classes are constructed. –Then all data members are constructed. –Then the constructor’s code is executed. The destruction is in reversed order. –Destructor’s code is executed. –Data members are destructed. –Base classes are destructed. If we do not “call” base’s constructor, it’s default constructor will be called.
OOP Etgar 2008 – Recitation 619 Who Should Do It? These “calls” to base’s constructor should be made in all derived’s constructors (including copy constructor). Other derived’s functions may need to “work with” base’s members. For example, operator= must assign to base’s members too. It’s easy by calling appropriate method from base. Compiler generated methods do this by default.
OOP Etgar 2008 – Recitation 620 operator= Example // Redundant operator=. Compiler-generated // would do the same. No need to check // self-assignment Student& Student::operator=(const Student& rhs) { Person::operator=(rhs);// Calls base's operator= _univ = rhs._univ; return *this; }