INHERITANCE


               7.1 Introduction: 
               Inheritance is a process of creating new classes, called derived classes from the existing class
               or base class. The  derived  class inherits  all  the capabilities of the base class but can add 
              members and refinements of its own. The base class is unchanged by this process. Inheritance has 
              important advantages. Most importantly, it permits code reusability. Reusability  is yet another
               important feature of OOP. C++ strongly supports the concept of reusability. The  C++ classes can 
               be reused in several ways. Once a class has been written and tested, it can be  adapted by other 
               programmers to suit  their  requirements. Creating new classes, reusing  the properties  of the
               existing ones, basically  does this. The mechanism of  deriving a new  class from an  old one is
               called inheritance (or derivation). The old class is referred to as the  base class and  the new 
               one is called the derived class.
 
               The  derived  class  inherits  some or all of  the traits  from the base class. A class can also
               inherit properties from more than  one class or  from more  than one level. A derived class with 
               only one base class is called single  inheritance  and one  with several base  classes is called
               multiple inheritance. On the other hand, more than one class may inherit the traits of one class.
               This process is known as hierarchical inheritance.The mechanism of deriving a class from another 
               'derived class'  is  known as multilevel inheritance. Figure shows  various forms of inheritance
               that  could be  used  for  writing extensible programs. The direction of arrow indicates the 
               direction of inheritance. 
 
               a)            Single inheritance:                                  b)  Multilevel inheritance
 
                  


              c) Multiple inheritance                                                   e) Hierarchical inheritance
 
                  



               7.2 Defining Derived Classes:  

              A derived class is defined by specifying its relationship with the base class in addition to its
               own details. The general form of defining a derived class is: 
 
               class derived-class-name : visibility-mode base-class-name 
                                              {
                                                             ---- //
                                                           ---- // members of derived class 
                                                             ----// 
                                              }; 
 
               The  colon indicates  that  the  derived-class-name  is derived  from the  base-class-name. The
               visibility  mode is  optional and,  if present,  may  be either private or  public. The default
               visibility-mode is private. Visibility mode specifies whether the features of the base class are
               privately derived or publicly derived.
 
               Examples: 
                               class ABC: private XVZ         //private derivation 
                               { 
                                              members of ABC 
                               }; 
                               class ABC : public XVZ         //public derivation 3
                               { 
                                              members of ABC 
                               }; 
                               class ABC : XVZ                   //private derivation by default 
                               { 
                                              members of ABC 
                               }; 
 
               When a derived class privately inherits a base class, 'public members' of the base class become 
               'private members' of the derived class and therefore the public members of the  base class  can 
               only be accessed by the member functions  of the  derived  class.They are  inaccessible  to the 
               objects of the derived class. Remember, a public member of a class can be accessed  by  its own 
               objects using the dot operator. The result is that no member of the base class is accessible to 
               the objects of the derived class.
 
               On the other hand, when the base class is publicly inherited, 'public members' of the base class 
               become 'public members' of the derived class and therefore they are accessible to the objects of
               the derived class. In both the cases, the private members are not inherited and therefore,   the
               private members of a base class will never become the members of its derived class. 

               In inheritance, some of the base class data elements and member functions are 'inherited'into the
               derived class. We can add our own data and member functions and thus extend the functionality of 
               the base class. Inheritance, when used to modify and extend the capabilities of the existing classes,
               becomes a very powerful tool for incremental program development.
 
  
              7.3 Single Inheritance: 
 
               A derived class with only one base class is called single inheritance.Consider the program below:
 
               # include < iostream.h> 
               class Counter                                                        // base class 
               { 
                               protected:                                                             // NOTE: not private 
                               unsigned int count;                                 // count 
                               public: 
                               Counter( ) { count = 0; }                       //constructor, no args 
                               Counter(int c) { count = c; }                  // constructor, one arg 
                               int get_count( ) { return count; }             // return count 
                               Counter operator ++ ( )                         // increment count 
                               { 
                                              count++;                                               // increment count, return 
                                              return Counter(count);                           //an unnamed temporary object 
                               }                                                                          // initialized to this count 
               }; 
               class CountDn : public Counter                             // derived class 
               { 
                               public: 
                               Counter operator --( )                                           // decrement count 
                               { 
                               count--;                                                 // decrement count, return 
                               return Counter(count);                           // an unnamed temporary object 
                               }                                                                          // initialized to this count 
               }; 
               void main( ) 
               { 
                               CountDn cl;                                                                          // c1 of class CountDn 
                               cout << "\ncl=" << c1.get-count();                        // display c1 
                               cl++;
                               cl++; 
                               cl++;                       
                               cout << "\ncl=" << cl.get-count( );                         // display it 
                               c1--; 
                               c1--; 
                               cout << "\nc1=" << c1.get-count( );                      // display it 
               }
 
               7.4 Accessing Base Class Members: 
 
               An important topic in inheritance is knowing when objects of the derived class can use a member 
               function in the base class. This is called accessibility.
 
              Substituting Base Class Constructors: 
               In the main ( ) part of  the above program: 
 
                               CountDn c1; 
 
               This causes c1 to be created as an object of class countDn and initialized to 0. There is no
               constructor in the CountDn class specifier, if you don't specify a constructor,the derived class 
               will use an appropriate constructor from the base class. This flexibility on the part of the compiler
               using one function because another isn't available is feature of inheritance. Generally the substitution
               is what you want, but sometimes it can be error also. 
               
               Substituting Base Class Member Functions: The object c1 of the countDn class also uses the 
               operator++( ) and get-count ( ) functions from the counter class. The first statement is used to 
               increment c1:
 
                               c1++;
 
               and the second statement is used to display the count in c1:
 
                               cout << "\nt1=" << t1.get_count( ); 
 
               Again the compiler, not finding these functions in the class of which c1 is a member, uses member 
               functions from the base class. The ++ operator, the constructors, and the get_count( ) function in 
               the counter class, and the - - operator in the countDn class, all work with objects of type countDn.
 
               7.5 Making A Private Member Inheritable (protected):
 
               C++ provides a third visibility modifier, protected,which serves a limited purpose in inheritance. A
               member declared as protected is accessible by the member functions within its class    and any class
               immediately derived from it.It cannot be accessed by the functions outside these two classes. A class 
               can now use all the three visibility modes as illustrated below. 
 
               class alpha { 
               private:                  //optional 
               ---.                         //visible to member functions 
               ---.                         //within its class 
               protected :
               ---.                         //visible to member functions 
               ---.                         //of its own and derived class 
               public : 
               ----.                        //visible to ail functions 
               ----.                        //in the program 
               }; 
               
               When a protected member is inherited in public mode, it becomes protected in the derived class too,
               and therefore is accessible by the member functions of the derived class. It is also ready for further 
               inheritance. A protected member, inherited in the private mode derivation,  becomes private in the 
               derived class. Although it is available to the member functions of the derived class, it is not available
               for further inheritance (since private members  cannot be inherited). Table summarizes how the visibility 
               of members undergo  modifications  when they are inherited. 
 
  
             Table: Visibility of inherited members 
    

 

Base class Visibility

Derived class visibility

 

Public derivation

 Private derivation

 

Private

Not inherited

Not inherited

 

Protected

Protected

Private

 

Pubic

Pubic

Private

 

 
             The keywords private, protected,and public may appear in any order and in any number of times in
               the declaration of a class. 
               For example, 
               class beta 
               { 
               protected : 
               ---.          
               public : 
               ---.          
               private:
               --..
               public : 
               ---.
               };
 
               is a valid class definition.
               However, the normal practice is to use them as follows:
 
               class beta 
             {              ---.          //private by default
               ---.          
               protected : 
               ---.          
               public : 
               ---.          
               }
 
               The following table summarizes the situation in a different way.

               

Access Specifier

Accessible fromOwn class

Accessible fromDerived class

Accessible fromObjects outside class

public

yes

Yes

Yes

Protected

yes

yes

No

Private

yes

No

No

  
               7.6 Derived Class Constructors:
 
               The compiler will substitute a no-argument constructor from the base class, when there is no 
               constructor for the derived class, but it draws the line at more complex constructors. To make 
               such a definition work we must write a new set of constructors for the derived class, consider 
               the program below.
 
               # include < iostream.h>  
               class Counter 
               {
              protected:                                                                            // NOTE: not private unsigned 
                               int count;                                               // count 
               public: 
                               Counter( ) { count = 0; }                       // constructor, no args 
                               Counter(int c) { count = c; }                  // constructor, one arg 
                               int get_Count( ) { return count.; }           // return count 
                               Counter operator ++ ( )                         //increment count 
                               { 
                                              count++;                                               // increment count, return 
                                              return counter(Count);                           // an unnamed temporary object 
                               }                                                                          // initialized to this count 
               }; 
               class countDn : public counter 
               { 
               public: 
               CountDn( ) : Counter( )          // constructor, no args 
                { }
               CountDn(int c) : Counter(c)    // constructor 1 arg 
                { } 
               CountDn operator --( )           // decrement count 
               { 
                   count--;                                             // decrement count, return 
                   return countDn(Count);       // an unnamed temporary object 
               }                                                           // initialized to this count 
               }; 
               void main( ) 
               { 
                               CountDn c1;                          
                               CountDn c2(100); 
                               cout << "\nc1=" << c1.get-Count( );       
                               cout << " \nc2=" << c2 .get-Count ( ) ;
                               c1++;
                               c1++; 
                              c1++;      
                               cout << "\nc1=" << c1.get-Count( );      
                               c2--;        c2--;                                                                     
                               cout << "\nc2=" << c2.get-Count( );      
                               CountDn c3 = c2--;                                              
                               cout << "\ric3=" << c3.get-Count( ); 
               } 
               This program uses two new constructors in the countDn class.Here is the one argument constructor:
 
                               CountDn( ) : Counter( ) 
                                              { } 
 
               This constructor has an unfamiliar feature: the colon followed by a function name.This construction 
               causes the CountDn ( ) Constructor to call the counter( ) constructor in the base class. In main( ),

               when we say  CountDn c1; 
 
               the compiler will create an object of type countDn and then call the countDn constructor to initialize 
               it.This constructor will in turn call the counter constructor: which carries out the work. The countDn( ) 
               constructor could add additional statements of its own, but in this case it doesn't need to, So the
               function body between the braces is empty. The statement: 
 
                               CountDn c2(100); 
 
               in main( ) uses the one-argument constructor in countDn  .This constructor also calls the corresponding 
               constructor in the base class: 
 
                               CountDn(int c) : Counter(c)         //argument c is passed to Counter 
                                              { } 
               This construction causes the argument c to be passed from countDn ( ) to  counter ( ) where it is
               used to initialize the object. In main( ) , after initializing the c1 and c2 objects, we increment
               one and decrement the other and then print the results. The one-argument Constructor is also used
               in an assignment statement: 
 
                               CountDn c3 = c2--; 
  
              7.7 Overriding member functions:

               You can use member functions in a derived class that have the same name as those in the base class.
               You might want to do this so that calls in your program work the same way for objects of both base 
               and derived classes. 
 
               // Program to demonstrate overloading functions in base and derived classes 
               # include < iostream.h> 
               # include < process.h>                                                         // for exit() 
               const int MAX = 100;                                                          // maximum size of stack 
               class Stack 
               { 
               protected:                                                                                            
                               int st[MAX];                                          
               public: 
                               Stack( )                                                                // constructor 
                       { top = 0; } 
                               void push(int var)                                                  // put number on stack 
                               {              st[++top] = var;      } 
                               int pop( )                                                                              // take number off stack 
                               { return st[top--]; } 
               }; 
                               class Stack2 : public Stack 
                              { 
                               public: 
                                              void push(int var)                                                  // put number on stack 
                               { 
                                              if(top < MAX)                                       // if stack not full,                
                              Stack::push(var);                              // call push( ) in Stack class else 
                              { cout << "\nError: stack is full"; 
                                         exit(1); 
                                      } 
                               }
                               int pop( )                                                                              // take number off stack 
                       { 
                               if(top > 0)                                                                            // if stack not empty, 
                          return Stack::pop( );                                   // call pop() in Stack class
                               else 
                                      { cout << "\nError: stack is empty"; exit(1); }
                    } 
               }; 
               void main( ) 
               { 
                               Stack2 51; 
                               s1.push(11);                           // push some values onto stack s1.push(22); 
                               s1.push(33); 
                               cout << endl << s1.pop( );                    // pop some values from stack 
                               cout << endl << s1.pop( ); 
                               cout << endl << s1.pop( ); 
                               cout << endl << s1.pop( );      
               } 
 
               7.8 Multilevel Inheritance:

              It is not uncommon that a class is derived from another derived class as shown.The class A serves
               as a base class for the derived class B that in turn serves as a base class for the derived class 
               C. The class B is known as intermediate base class since it provides a link for the inheritance 
               between A and C. The chain ABC is known as inheritance path. 
 
                    


              A derived class with multilevel inheritance is declared as follows: 

               class A{ };                                            //Base class 
               class B: public A { };                             //B derived from A 
               class C: public B { };                             //C derived from B 
 
  
 
              This process can be extended to any number of levels. Let us consider a simple example. Assume that
               the test results of a batch of students are stored in three different classes. Class student stores
               the roll-number, class test stores the marks obtained in two subjects and class result contains the 
               total marks obtained in the test. The class result can inherit the details of the marks obtained in 
               the test and. the roll_number of students through multilevel inheritance. Example: 
 
               # include < iostream.h> 
               class student 
               { 
               protected: 
                               int roll_number; 
               public: 
                               void get-number(int) ; 
                               void put-number(void); 
               };
 
                               void student :: get-number(int a) 
                               { roll-number = a; }
 
                               void student :: put-number() 
                               { cout << "Roll Number: " << roll-number << "\n";  }
 
               class test: public student                                        //FIRST LEVEL DERIVATION 
               {
               protected: 
                               float subl; 
                               float sub2; 
               public: 
                               void get-marks(float, float) ; 
                               void put-marks(void) ; 
               };
 
                               void test :: get-marks(float x, float y) 
                               { subl = x;. sub2 = y; } 
 
                               void test: : put-marks() 
                               { 

                              cout << "Marks in SUBl = " << subl << "\n" ;
                               cout << "Marks in SUB2 = " << sub2 << "\n"; 
                               }
 
               class result : public test                           //SECOND LEVEL DERIVATION 
               { 
                               float total;                                              //private by default 
               public: 
                               void display (void) ; 
               } ;
 
                               void result :: display(void) 
                               { 
                               total = subl + sub2;
                               put_number ( ) ; 
                               put-marks ( ) ; 
                               cout << "Total= " << total << "\n";
                               }
 
               main( )
               { 
                               result student 1;                      //studentl created 
                               studentl.get-number(lll) ; 
                               studentl.get-marks(75.0, 59.5) ; 
                               studentl.display( ) ;
               }              
 
               7.9 Multiple Inheritance: 
 
               A class can inherit the attributes of two or more classes. This is known as multiple inheritance.
               Multiple inheritance allows us to combine the features of several existing classes as a starting
               point for defining new classes. It is like a child inheriting the physical features of one parent
               (papa) and the intelligence of another (mama). The syntax of a derived class with multiple base 
              classes is as follows: 
 
               Class D : visibility B-1, visibility B-2, 
               { 
               -----
               ----- (Body of D) 
               -----
               }; 
 
               where, visibility may be either public or private. The base classes are separated by commas. 
               Example:
 
               # include < iostream.h> 
               class M 
               {
                               protected: 
                               int m; 
               public: 
                               void get-m(int) ; 
               } ;
               class N 
               {
               protected: 
                               int n; 
               public: 
                               void qet-n(int) ; 
               } ; 
               class P : public M, public N 
               { 
               public: 
                               void display(void) ; 
               } ;
                               void M ::get-m(int x) 
                               {  m = x;  }
                               void N : : get-n(int y) 
                               {               n = y;                     } 
                               void P ::display(void) 
                               { 
                               cout << "m = " << m << "\n"; 
                               cout << "n = " << n << "\n"; 
                               cout << "m*n = " << m*n << "\n";
                               }
               main( )  
                {
                               P p; 
                               p.get-nl(10) ; 
                               p.get-n(20) ; 
                               p.display( ) ; 
               }
 
  
              7.10 Hybrid Inheritance: 

               There could be situations where we need to apply two or more types of inheritance to design a 
               program.For instance, consider the case of processing the student results. Assume that we have
               to give weightage for sports before finalising the results. The weightage for sports is stored 
               in a separate class called sports. The new inheritance relationship between the various classes
               would be as shown in Fig. Below: 

                               

             # include < iostream.h>
               class student

              {
               protected: 
                              int roll-number; 
               public: 
                               void get-number(int a) 
                               {              roll-number = a;      } 
                               void put-number(void)  
                               {              cout << "Roll No: " << roll number << "\n"; } 
               } ; 
               class test: public student  
               {
               protected: 
                               float partl, part2; 
               public: 
                               void get_marks(float x, float y) 
                               {               partl = x; part2 = y;               } 
                               void put_marks(void)  
                               {              
                               cout << "Marks obtained: " << "\n" << "Fartl = " << partl << "\n" 
                                                                            << "Fart2 = "<< part2 << "\n" ; 
                               }
                               };
                               class sports  
                               {
                               protected: 
                                              float score; 
                               public: 
                                              void get-score(float s) 
                                              {               score = s;               }
                               void put-score(void) 
                               {              cout << "Sports wt: " << score << "\n\n"; } 
               } ; 
               class result: public test, public sports 
               { 

                              float total; 
               public: 
                               void display(void) ; 
               }; 
                               void result :: display(void) 
                               { 
                               total = partl + part2 + score; 
                               put_number ( ) ; 
                               put_marks ( ) ; 
                               put_score ( ) ; 
                               cout << "Total Score: " << total << "\n"; 
                               }
               main ( ) 
               { 
                               result student_l; 
                               student_l. get_number (1234) ; 
                               student_1.get_nlarks(27.5, 33.0) ; 
                               student_1.get_score(6.0) ; 

                              student_1.display( ) ; 
               }
 
 
 
              7.11 Containership: Classes Within Classes: 
              In inheritance, if a class B is derived from a class A, we can say "B is a kind of A". This is
               because B has all the characteristics of A, and in addition some of its own.  For this reason 
               inheritance is sometimes called a "kind of" relationship:
              There's another  kind of relationship,  called a "has a"  relationship, or  containership. In 
               object-oriented programming the "has a" relationship occurs when one object  is  contained in 
              another. Here's a case where an object of class B is contained in a class A: 
               class A 
              { 
                               B b;                        // b is an object of class B 
               }; 
               class B 
               { }; 
 
               In some situations inheritance and containership relationships can serve similar purposes.
               The following program shows these relationships in a different way: 
 
               # include < iostream.h> 
               const int LEN = 80;                                              // maximum length of names 
               class student                                                         // educational background 
               { 
               private: 
                               char school[LEN];  // name of school or university 
                               char degree[LEN];  // highest degree earned 
               public:
                               void getedu( ) 
                               { 
                               cout << " Enter name of school or university: "; 
                               cin >>school; 
                               cout << " Enter highest degree earned \n"; 
                               cout << " (High school, Bachelor's, Master's, PhD): "; 
                               cin >>degree; 
                               } 
                               void putedu( ) 
                               { 
                               cout << "\n School or university: " << school; 
                               cout << "\n Highest degree earned: " << degree; 
                               } 
               }; 
               class employee 
               { 
               private: 
                               char name(LEN];                   // employee name 
                               unsigned long number;            // employee number 
               public: 
                               void getdata( ) 
                               { 
                               cout << "\n Enter last name: "; 
                               cin >>name; 
                               cout << " Enter number: "; 
                               cin >>number; 
                               } 
                               void putdata( ) 
                               { 
                               cout << "\n Name: " << name; 
                               cout << "\n Number: " << number; 
                               }
                }; 
               
               class manager                                                                       // management 
               { 
               private: 
                               char title(LEN];                      // "vice-president" etc. 
                               double dues;                                          // golf club dues 
                               employee emp;                       // object of class employee
                               student stu;                                            // object of class student 
               public: 
                               void getdata( ) 
                               { 
                               emp,getdata(); 
                               cout << " Enter title: ";                                           cin >>title; 
                               cout << " Enter golf club dues: " ;           cin >>dues; 
                               stu.getedu( ); 
               } 
               void putdata( ) 
               { 
               emp.putdata( ); 
               cout << "\n Title: " << title; 
               cout << "\n Golf club dues: " << dues; 
               stu.putedu( );
               }
               }; 
 
               class scientist                                                                        // scientist 
               { 
               private: 
                               int pubs;                                 // number of publications 
                               employee emp;                       // object of class employee 
                               student stu;                                            // object of class student 
               public: 
                               void getdata( ) 
                               { 
                               emp.getdata( ); 
                               cout << " Enter number of pubs: "; 
                               cin >>pubs; 
                               stu.getedu( ); 
                               }
                               void putdata() 
                               { 
                               emp.putdata( ); 
                               cout << "\n Number of publi cations: " << pubs;
                               s u.putedu( );
                               }
               };
               class laborer                                                                         //laborer  
               {
               private: 
                               employee emp;                       // object of class employee 
               public: 
                               void getdata( ) 
                               { emp.getdata( ); } 
                               void putdata( ) 
                               { emp.putdata( ); } 
               }; 
               void main( ) 
               { 
                             manager m1; 
                               scientist s1, s2; 
                               laborer l1; 
                               cout << endl; 
                               cout << "\nEnter data for manager 1";                    // get data for 
                               m1.getdata( );                                                                       // several employees
                               cout << "\nEnter data for scientist 1";                     s1.getdata( ); 
                               cout << "\nEnter data for scientist 2";                     s2.getdata( ); 
                               cout << "\nEnter data for laborer 1";                                     l1.getdata( ); 
                               cout << "\nData on manager 1";                                            m1.putdata( );  
                               cout << "\nData on scientist 1";                                             s1.putdata( ); 
                               cout << "\nData on scientist 2";                                             s2.putdata( ); 
                               cout << "\nData on laborer 1";                                              l1.putdata(); 
               } 
 
               Containership is clearly useful with classes that act like a data type. Then an object of that 
               type can be used in a class in almost the same way a variable would be. In other situations you 
               will need to examine the problem carefully and  perhaps try  different approaches to see what 
               makes sense. Often  the inheritance relationship is simpler  to implement and offers a clearer                
               conceptual framework. 
 
               Exercise:

              1.The class master derives information from both accounts and admin classes, which in turn 
                derive information from the class person. Define all four classes and write a program to create,
                update and display the information contained in master objects.
 
               2. Start with three classes Publication, Book and Tape, add a base class sales hat holds an
                array of three floats so that it can record the sales of a particular publication. Write a program 
                to use these classes.
 
               3. Using the techniques of OOPs design a program that would simulate a simple real world system 
                familiar to you