180 likes | 204 Views
DERIVED CLASSES AND INHERITANCE. Moshe Fresko Bar-Ilan University Object Oriented Programing 2007-2008. Derived Classes. Consider the example (Composition): struct Employee { string firstName, lastName ; char middleInitial ; Date hiringDate ; short department ; // … }
E N D
DERIVED CLASSES AND INHERITANCE Moshe Fresko Bar-Ilan University Object Oriented Programing 2007-2008
Derived Classes • Consider the example (Composition): struct Employee { string firstName, lastName ; char middleInitial ; Date hiringDate ; short department ; // … } struct Manager { Employee emp ; set<Employee*> group ; short level ; // … } • A Manager is an Employee. But compiler does not know it.
Derived Classes Employee • Better way: struct Manager: public Employee { set<Employee*> group ; short level ; // … } • Manager is derived from Employee. (Derivation) • Or Employee is a Base class for Manager. • Manager has all the members of Employee in addition to its own members. • A derived class inherits properties from its base, so the relationship is called Inheritance. Manager
Derived Classes • Manager is a subtype of Employee, so wherever Employee is needed Manager can be used. void f ( Manager m1, Employee e1) { Employee* elist[2] ; elist[0] = &m1 ; elist[1] = &e1 ; // … }
Casting • If a class “Derived” has a public base class “Base” then a “Derived*” can be assigned to a variable of type “Base*” without explicit casting. The opposite conversion must be explicit. • Manager is an Employee, but Employee is not necessarily a Manager. void g ( Manager mm, Employee ee) { Employee* pe = &mm ; // ok: Manager* pm = &ee ; // error: pm->level = 2 ; // Catastrophic pm = static_cast<Manager*>(pe) ; // works. pm->level = 2 ; // fine. // … }
Member Functions • A member of a derived class can use the public and protected members of its base class. class Employee { string firstName, lastName; char middleInitial; public: void print() const ; string fullName() const { return firstName+‘’+middleInitial+‘’+lastName; } // … } class Manager: public Employee { // … public: void print() const ; // … } void Manager::print() const { cout << “name is “ << fullName() << endl ; // but cannot use lastName, it is private }
Member Functions • To call the version from the Base class void Manager::print() const { Employee::print() ; // print Employee information // Print Manager specific information cout << “Level:” << level << endl ; }
Constructors and Destructors • Base constructor called first. Derived class either must specify the Base constructor or must count on the default Base constructor (if there is one). class Employee { string firstName, lastName; short department; public: Employee(const string& n, int d); /*…*/ } class Manager: public Employee { set<Employee*> group; short level; public: Manager(const string&n, int d, int lvl); /* … */ } Employee::Employee(const string& n, int d) : lastName(n), department(d) { /* … */ } Manager::Manager(const string& n, int d, int lvl) : Employee(n,d), level(lvl) { /* … */ }
Constructors and Destructors • First ctor of base class and then of derived class. • First dtor of derived class and then of base class. class A { public: A() { cout << “ctor:A()” << endl ; } public: ~A() { cout << “dtor:~A()” << endl ; } } class B : public A { public: B() { cout << “ctor:B()” << endl ; } public: ~B() { cout << “dtor:~B()” << endl ; } } int main() { A a ; B b ; } // what will be the output of the program
Constructors and Destructors • There must be a suitable ctor in Base class. class A { private: int val; public: A(int x) { val=x ;} } class B: public A { public: B(int x) : A(x) { } B(int x) { } // error B() : A(5) { } B() { } // error } class C: public A { // error no ctor for C }
Copying of class Objects • Copying of class objects is defined by the copy constructor and assignments. class Employee { // … Employee& operator=(const Employee&); Employee(const Employee&); }; void f(const Manager& m) { Employee e=m ; // slicing Employee e2 ; e2 = m ; // Use employee part of Manager }
Class Hierarchies • A derived class can itself be a base class. class Employee { /*… */ }; class Manager : public Employee { /* … */ }; class Director : public Manager { /* … */ }; • Multiple Inheritance class Temporary { /* … */ }; class Secretary : public Employee { /* … */ }; class Tsec : public Temporary, public Secretary { /* … */ }; class Consultant : public Temporary, public Manager {/*…*/};
Virtual Functions • For Virtual Functions the compiler and loader will guarantee the correct correspondence. class Employee { string firstName, lastName; short department; // … public: Employee(const string& n, int dept); virtual void print() const; // … }; void Employee::print() const { cout << lastName << “\t” << department << endl ; }
Virtual Functions • A function from a derived class with the same name and the same set of argument types as a virtual function in a base is said to override the function. class Manager : public Employee { set<Employee*> group ; short level ; // … public: Manager (const string& n, int dept, int lvl); void print() const ; // … } void Manager:print() const { Employee::print(); cout << “\tlevel=” << level << endl ; }
Virtual Function calls • Polymorphism: Getting the right behavior from Employee’s functions independently of exactly what kind of Employee is actually used is called polymorphism: A type with virtual function is called a polymorphic type. void print_one_employee(Employee* ep) { ep->print() ; } int main() { Employee e(“Brown”, 1234) ; Manager m(“Smith”, 1234, 2) ; Employee* ep = &e ; print_one_employee ( ep ) ; ep = &m ; print_one_employee ( ep ) ; } // What will be the output ?
Abstract Classes • Pure Virtual Functions: A virtual function is made pure by the initializer of =0 • Abstract Class: A class with at least one virtual function is called an abstract class, no Objects of the abstract class can be created. class Shape { public: virtual void rotate(int) = 0 ; virtual void draw() = 0 ; }; Shape s ; // error Shape* sp ; // ok
Abstract Class • An abstract class can be used as an interface and as a base for other classes. class Point { /* … */ }; class Circle: public Shape { public: void rotate(int x) { /*…*/ } void draw() { /*…*/ } Circle(Point p, int r); private: Point center; int radius; }
Exercise • Create a class NameWriter with a virtual function writeName that prints the name of the class. Derive A and B classes and override this function. • Create a list of 10 pointers to NameWriter. Fill them with pointers to objects of classes A and B. • Write a global function that calls writeName for a list of NameWriter-s. • For 2 call the function in 3. • Delete the virtual keyword from writeName function declaration and run the program again.