OOP, Virtual Functions and Inheritance CS 2133: Data Structures OOP, Virtual Functions and Inheritance
Inheritance C++ Classes provide a way to enforce the walls of data abstraction by encapsulating the data and operations. Inheritance and polymorphism allow you to derive new classes from existing classes. Software reusability is the main reason we do this. Life Animals Plants Snakes Dogs Rats Grass Orchid
Inheritance Direct Inheritance Multiple Inheritance Animal Vehicle Toy Base Mammal SUV Horse Direct Inheritance Multiple Inheritance Represents derived classes Represents base classes
Syntax of Inheritance Public Subclass Class Vehicle{ // base class float mph; float weight; } Class Car: public Vehicle { // derived class char brand_name[100]; Public Subclass
Member Accessibility A private member may be accessed only by methods within its class or by friends A protected member may be accessed only by methods with its class hierarchy or friends A public member is globally accessible
Public Inheritance Each public member in the base class is public in the derived class Each protected member in the base class is protected in the derived class Each private member in the base class remains private in the base class and so is visible only in the base class
Private Inheritance Each public member in the base class is private in the derived class Each protected member in the base class is private in the derived class Each private member in the base class remains private in the base class and so is visible in the base class
Protected Inheritance Each public member in the base class is protected in the derived class Each protected member in the base class is protected in the derived class Each private member in the base class remains private in the base class and so is visible in the base class
Protected Example Which is Legal? class BC{// base class public: void set_x( int a ){x=a;} protected: int get_x() const{return x;} private: int x; }; class DC: public BC { void add(){ int c = get_x(); set_x( c+2); } int main(){ DC d; d.set_x(3); cout<<d.get_x<<‘\n’; d.x =234; d.add(); }; Which is Legal?
Example of Public Inheritance Class B{// base class public: int x; protected:int w; private: int z; }; class D: public B{ public: int y; void set_w(int z) { w=a;} void base_w(B b) { b.w=0;} int main() { D d; d.x = 33; d.y = 33; d.w = 77; d.z = 88; } BAD Which is Legal?
Further Discussion Why is this bad? void base_w(B b) { b.w=0;} A derived class may access protected members that it inherits from a base class. A derived class may access these protected members precisely because, once inherited, they belong to the derived class A derived class may not access protected members of a base class object, that is, an object that belongs to the base class but not to the derived class.
Notes about Inheritance A private member is inherited but not visible in a derived class. Except for a friend function, only methods of a class can access a private member of that class A protected member is inherited and visible in a derived class. In general protected data should be avoided. The data can be made private and made accessible by protected accessors. For example, a class with private data members and protected accessors can be completely re-implemented without disturbing the interface.
Name Hiding A member in a derived class of the same name as the base class hides it. The scope resolution operator can be used if access to the base class member is required. If a derived class adds a method with the same name in the base class, the added method hides the base class’s method
Name Hiding Example class BC{//base class public: void h(float); //BC::h }; class DC: public BC{ // derived class void h( char[ ]); // danger: hides BC::h int main(){ DC d1; d1.h(“Data Structures!”); // DC::h d1.h(707.7); // ****ERROR: DC::h hides BC::h d1.BC::h(707.7); // OK BC::h }
Constructors under Inheritance class Animal{ protected:char species[MaxName+1]; public: Animal() { strcpy(species, “ Animal”); } Animal(char* s) { strcpy(species, s);} }; class Primate: public Animal{ protected: heartcham; Primate(): Animal(“Primate”){} Primate(int n): Animal(”Primate”){heartcham=n;} } class Human: public Primate{ Human(): Primate(){}; Human(int c):Primate(c){} executes first Animal::Animal() Primate:Primate() Human::Human()
Destructors under Inheritance Constructors in an inheritance hierarchy fire in a a base class to derived class order Destructors in an inheritance hierarchy fire in a derived class to a base class order Constructors may not be virtual but destructors may be. Used when constructors for the base and derived class dynamically allocated separate storage and the program dynamically allocates a class object
Constructors firing rules assume D is derived from B If D has constructors but B has no constructors, then the appropriate D constructor fires automatically If D has no constructors but B has constructors, then B must have a default constructor so that B’s default constructor can fire whenever a D object is created. If D has constructors and B has a default constructor, then B’s default constructor fires automatically unless another is explicitly invoked. If D and B have constructors but B has no default constructor, then each D constructor must explicitly invoke, in its header, a B constructor.
What is the output? class B{ public:B( ) { cout << “B” << endl; } }; class D1:public B{ public:D1( ):B( ) { cout << “D1” << endl; } class D2: public D1( ){ public: D2( ): D1( ) {cout << “D2” << endl; D2 d; Output:B D1 D2
Polymorphism & Virtual Methods Polymorphism is the runtime binding of a pointer to a method Non-virtual methods are bound at compile time A method that needs to be bound at runtime is labeled Virtual. Only methods may be virtual
Polymorphism class Pet{ }; class Dog:public Pet{ public:virtual sound{cout<<“Bark”<<endl;} class Cat:public Pet{ public:virtual sound{cout<<“Meow”<<endl;} Pet Dog Cat Cat c; Dog d; Pet * ptr1, ptr2; ptr1 = &c; ptr2=&d; ptr1-> sound(); ptr2-> sound();
Inheritance and Virtual Methods A pointer that points to a base class may also point to a subclass without casting. The reverse direction is not allowed. Once virtual always virtual. Figure * ptr Figure Ellipse Rect Circle
Pure Virtual Methods (Support for Programming Design) An abstract class is a base class that is required to have a derived class. No object may be dreated for an abstract class An abstract class is one that has a pure virtual method in its class declaration Class Pet { //abstract class public: virtual void sound()=0; }
Multiple Inheritance class Win{ //base class ... } class ScrollWin: public Win{ Widget horizontalSB; Widget verticalSB; class PopupMenu{ protected: int menuChoices; Win * menuSubWins; ... } class ScrollPopupMenu: public PopupMenu, public ScrollWin{ Win ScrollWin PopupMenu ScrollPopupMenu
Virtual Base Classes class B{//base class protected; int x; } class D1: public virtual B{ protected: ... class D2: public virtual B{ protected: ... } class Z: public D1,public D2{ }; Note that the variable x gets inherited from B along two different paths. The virtual base classes guarantees that only one copy of x arrives at Z
Common Error (Slicing an Object) In C++ it is legal to copy a derived-class object into a base class variable. For example, when a Manager object is assigned to a variable of type Employee, the result is only the employee portion of the manager data; Manager m; Employee e=m // holds onlyt the Employee data The reverse assignment is not legal!