12

Inheritance

LEARNING OBJECTIVES

At the end of this chapter, you should be able to

  • Use inheritance to extend a new class from the existing classes.
  • Understand the types of inheritances and concepts therein.
  • Understand the concepts of ADT, virtual functions, and dynamic data binding.

12.1 Introduction

The concept of inheritance is not new to us. We inherit property, goodwill and name from our parents. Similarly, our descendants will derive these qualities from us. Reusability of code is one of the strong promises that are made by C++ and inheritance is the tool selected by C++ to fulfill this promise. In this chapter, we take you through inheritance and its properties and rules. We will dwelve into the terminology of inheritance and the types of inheritances. We will introduce the reader to overloading and overriding concepts and introduce the various types of inheritances through examples. We will also cover the virtual functions and ADTs in detail. Each concept you will learn through an example.

12.2 Inheritance Hierarchy

Study the inheritance hierarchy shown in Figure 12.1. Human and Animal derive qualities from living beings. Professionals, students and Athletes are derived from Human. We say these three categories have inherited from Human. Class Human is called base class and Student and Athlete are called derived classes. What can be inherited? Both member functions and member data can be inherited. Have you noticed the direction of the arrow to indicate the inheritance relation? It is pointed upwards as per modelling language specifications

 

Inheritance hierarchy

 

Figure 12.1 Inheritance hierarchy

 

Inheritance specifies is type of relation. Observe that a Student is a Human. Similarly Mammal is Animal. Human is a base class and Student is a derived class. Derivation from base class is the technique to implement is type of relation. When do we use Inheritance? You inherit so that you can derive all the functionality and member data from base class and derived class can add its own specialized or individualistic functionality. For example, Athlete derives all functionality and attributes of Human and in addition adds sports and Athletic functionality and attributes on its own.

 

Example 12.1:    Syntax for Inheritance

class Human
{ public:
   protected: // variables declared as protected are public to
   derived classes
// protected variables
};
// Student inherited from Human , inheritance type is public
   class Student : public Human
{ public:
private:
};

Note that members declared as private are not available to derived class. If you make these member data as public then security is compromised. So what is the way out? Declare the member data as protected. Protected variables mean that these variables are public to derived classes and private to other classes.

If a public member function has the object, i.e. object has invoked the member function, then that function can access all the public member functions and public member data. Public functions of a class can access all the private member data and member functions of its own class and protected member data and member functions of their base classes.

 

Example 12.2:    inherit1.cpp Program to Show Inheritance with Derived Class and Base Class

1. #include <iostream>
2. using namespace std;
3. class BaseClass
4. { public:
5. void SetBase(int a, int b) { length = a; bredth = b; }
6. void DisplayBase(){ cout <<”length:”<<length << “ : “ <<”bredth:”<<bredth <<endl; }
7. protected:
8. int length, bredth;
9. };
10. // public inheritance
11. class DerivedClass : public BaseClass
12. { public:
13. DerivedClass(int x) { height = x; }
14. void DisplayDerived() { cout <<”Height:”<< height <<endl; }
15. private:
16. int height;
17. };
18. void main()
19. { // create an briefcaseject of derived class height=20
20. DerivedClass briefcase(10);
21. briefcase.SetBase(25,30); // access member of base
22. cout<<”
access & display member of base class”<<endl;
23. briefcase.DisplayBase(); // access member of base
24. cout<<”
Access & display members of derived class”<<endl;
25. briefcase.DisplayDerived(); // uses member of derived class
26. }//end of main
/*Output: access & display member of base class : length:25 : bredth:30
Access & display members of derived class : Height:10 */
Line No. 11 Base class extends i.e. derives from Base class
Line No. 20 A derived Class object briefcase has been created Height=10
Line No. 21 DC, briefcase accesses BC and sets its length and Bredth
Line No. 23 & 25 briefcase displays both base class and derived class data

12.3 Types of Inheritance

Inheritance means ability to derive a descendant class from base class. So in how many ways can we do that? We will refer to BC for base class and DC for derived class.

Single Inheritance: Figure 12a. DC is derived from the base class

 

Single inheritance

 

Figure 12.2a Single inheritance

Multiple Inheritance: In Figure 12.2b, multiple inheritance is at display. Note that subclass DC# has inherited from DC2 and also from DC1. Base class is virtual because both DC1 & DC2 have only one base class but each derived class feels that it has its own base class. Hence, the term “virtual”. Thus, we can also call this type of inheritance as inheritance with virtual base class.

 

Multilevel inheritance

 

Figure 12.2b Multilevel inheritance

Multilevel Inheritance: Figure 12.2c is self-explanatory

 

Multi level inheritance

 

Figure 12.2c Multi level inheritance

Hierarchical Inheritance: Figure 12.2d is self-explanatory

 

Hierarchical inheritance

 

Figure 12.2d Hierarchical inheritance

Hybrid Inheritance: Figure 12.2e. DC1 and DC2 are derived from BC. Hence base class is virtual base class. However, DC3 is derived from both DC2 & DC3. DC3 holds properties and data partly from DC2 and DC3 and also from DC as per design. Hence, this type of inheritance is called Hybrid Inheritance.

 

Hybrid inheritance

 

Figure 12.2e Hybrid inheritance

12.4 Constructors and Destructors

When we are creating object of derived class like Student, notice that Student constructor will call the base class constructor Human and first constructs Human portion of member data like idNo and name. Then Student constructor will initiate its own part of data like Category called CAT.

Similarly, when an object has to be destroyed, the derived class destructor class will be called first, followed by base class destructor. Notice also that derived classes, in addition to importing the functionality of base class like Work() and Learn(), add their own functionality like UseNet() and UseGym(). This is the way Inheritance is to be used. Inherit but add your own functionality in derived classes.

12.5 Base Class Function Overriding

Base class Human defines two functions, namely, Work() and Learn(). Derived class, if it does not define these functions once again, it can use base class learn(0) or Work(). But if it wants its own implementation, different from base class, it can define these functions in its class definition.

void Learn(){ cout<<”
 Students learn professional subjects… ”<< endl;}
void Work(){ cout<<”
 Students work at college laboratories… ”<< endl;}

When derived class object calls these functions, it will get derived class functionality only but NOT the base class functionality. If derived class object specifically needs the base class functionality, then it must call base class function using scope resolution operator as shown below:

cout<<”
 Student does Work() belonging to base class “<<endl;
std.Human::Work();

 

Example 12.3:    inherit2.cpp Program with Constructors and Destructors

1. #include<iostream>
2. using namespace std;
3. enum CAT { BTECH,MBA,MCA,MSC}; // Category of student
4. enum BAT { ATHLETE,SPORTS}; // Batch of Athlete or sports person
5. class Human
6. { public:
7. Human():idNo(0),name(“Noname”) //Base constructor
8. {cout<<”
 default Human constructor..”<<endl;}
9. Human(int n , char *p):idNo(n),name(p) // Base overloaded constructor
10. {cout<<”
Human constructor..”<<endl;}
11. ~Human(){cout<<”
Human destructor..”<<endl;} // base destructor
12. // Public functions
13. int GetReg()const{return idNo;}
14. void SetId(int n) { idNo=n;}
15. char * GetName() const { return name;}
16. void SetName( char *p) { name=p;}
17. void Learn()const{ cout<<”
 Human beings strive to learn …”<<endl;}
18. void Work()const { cout<<”
 Human work ….”<<endl;}
19. protected:
20. int idNo;
21. char *name;
22. };
23. class Student : public Human
24. { public:
25. Student():Human(),stcat(BTECH){cout<<”
Student constructor.. ”<<endl;}
26. Student(int n , char *p ):Human(n,p),stcat(BTECH)
27. {cout<<”
 Student(int n, char *p) constructor..”<< endl;}
28. ~Student(){}; // Default destructor
29. CAT GetCAT() const { return stcat;}
30. void SetCAT ( CAT c) { stcat=c;}
31. //students do differently functions
32. //void Learn(){ cout<<
 Students learn professional subjects…” endl;}
33. //void Work(){ cout<<
 Students work at college laboratories…” endl;}
34. void Play() { cout<<”
 Students play at college and at home… ”<<endl;}
35. void UseNet(){ cout<<”
 Students use internet for learning..”<<endl;}
36. private:
37. CAT stcat; // students category
38. };
39. void main()
40. { Student std(50,”Thunder”);
41. std.Learn(); std.Work();std.UseNet();
42. cout<<”
 Students name is :”<<std.GetName()<<endl;
43. cout<<”
 Explicit call to base class work………..”<<endl;
44. std.Human::Work(); // explicit call to base class work
45. }
46. /*Output : Human constructor..
47. Student(int n, char *p) constructor..
48. Human beings strive to learn …
49. Human work ….
50. Students use internet for advancement…
51. Students name is :Thunder
52. Explicit call to base class work………..
53. Human work ….
54. Human destructor..*/
Line No. 2 & 3: Declare enum data type CAT & BAT.
Line No. 7 & 9: Base class constructors class Human.
Line No. 13 & 16: public accessory functions
Line No. 17 & 18: implements two functions of Human work() & Learn()
Line No. 23: Student class inherits public from Human
Line No. 25: Student constructor first call base class constructor Human to set id No and Name and then sets its variables like CAT
Line No. 32 & 33: void Learn(){ cout<< Students learn professional subjects…”endl;}
  void Work(){ cout<< Students work at college laboratories…”endl;}
  show that Student over rides base class functions work() and Learn() at Line No. 17 &18.
Line No. 34 & 35: Student Declares its own functions like Play() & UseNet()
Line No. 40: Student std(50,”Thunder”); creates an object std of type Student. Firstly it calls base class constructor Human. ( Line No 44), then calls for Student(int , char *) constructor and completes the creation of object.
Line No. 41: std.Learn(); std.Work();std.UseNet(); are invoked by object std. As we have commented out statement 32 & 33 , learn() and Work() of base class Human are invoked as shown in line 46 & 47.
Line No. 52 & 53: Show explicit call to base class over ridden function

If you remove comment from 33 & 34 and recompile and run you will see Student objects Learn() and Work() will be invoked since they have overridden base class functions. Human constructor.

Student(int n, char *p) constructor..
Students learn professional subjects…
Students work at college laboratories
Students use internet for advancement…
Students name is: Thunder
Human destructor.

In our next example, we would work out two derived classes, namely, Student and Athlete

 

Example 12.4:    inherit3.cpp Program to Show Inheritance with Two Derived Classes

Copy Line No. 1 to 38, i.e. up to declaration of Students class prior to statement 1 and compile.

1. class Athlete : public Human
2. { public:
3. Athlete():Human(),atcat(SPORTS)
4.   {cout<<”
 Athlete constructor..”<<endl;}
5. Athlete(int n , char *p ):Human(n,p),atcat(SPORTS)
6. {cout<<”
 Athlete(int n, char *p) constructor..”<<endl;}
7. ~Athlete(){}; // Default destructor
8. BAT GetBAT() const { return atcat;}
9. void SetBAT ( BAT c) { atcat=c;}
10. // Athletes do differently functions
11. void Play() { cout<<”
 Athletes play at college and at home… ”<<endl;}
12. void UseGym(){ cout<<”
 Athletes use GYM for advancement… ”<<endl;}
13. private: BAT atcat; // Athletes category
14. };
15. void main()
16. { Human hum(53,”Ramesh”);
17. Student std(27,”Anand”);
18. Athlete atd(25,”Gautam”);
19. cout<<”
Human name is :”<<hum.GetName()<<endl;
20. cout<<”
Students name is :”<<std.GetName()<<endl;
21. cout<<”
 Athletes name is :”<<atd.GetName()<<endl;
22. cout<<”
 Objectof Human….”<<endl;
23. hum.Work();
24. hum.Learn();
25. cout<<”
 Objectof Student….”<<endl;
26. cout<<”
 Student works like Human. Student inherits Work() from Human”<<endl;
27. std.Work();
28. cout<<”
 Student does his own thing like UseNet “<<endl;
29. std.UseNet();
30. cout<<”
 Objectof Athlete….”<<endl;
31. cout<<”
 Athlete learns like Human. Athlete inherits Learn() from Human”<<endl;
32. atd.Learn();
33. cout<<”
Athlete does his own thing like UseGym “<<endl;
34. atd.UseGym();
35. }
/*Output :Human constructor..
Human constructor..
Student(int n, char *p) constructor..
Human constructor..
Athlete(int n, char *p) constructor..
Human name is :Ramesh : Students name is :Anand : Athletes name
is :Gautam
Objectof Human. Human work . : Human beings strive to learn :
Objectof Student.
Student works like Human. Student inherits Work() from Human
Human work
Student does his own thing like UseNet :Students use internet
for learning..
Objectof Athlete : Athlete learns like Human. Athlete inherits
Learn() from Human
Human beings strive to learn
Athlete does his own thing like UseGym : Athletes use GYM for
advancement
Human destructor.. Human destructor.. : Human destructor..*/

We leave analysis of output statements and invoking of constructors and destructors vis à vis the code as an exercise for the reader.

12.6 Base Class Function Hiding

When a derived class overrides a base class function and if the base class function has been overloaded three times, then except for the function that is overridden, the other two overloaded functions are hidden and not available. For example, let us say that Work() has been overloaded in a base class called Human as shown below:

void Work()const { cout<<”
 Human work ….”<<endl;}
void Work(int n) const {cout<<”
 Human work full speed…”<<endl;
void Work(int n, int p) const { cout<<”
 Human work round the
clock…”<<endl;

Now if derived class Student overrides one of the base class say void Work(), then the balance two functions, void Work(int n) const and void Work(int n , int p) const, are hidden and not available using derived class Student object.

 

Example 12.5:    inherit4.cpp Program to Show Base Class Function Hiding

1. #include<iostream>
2. using namespace std;
3. class Human
4. {public:
5. void Learn()const{ cout<<”
 Human beings strive to learn   …”<<endl;}
6. void Learn(int f)const{ cout<<”
 Humans learn at good speed…    ”<<endl;}
7. void Learn(int f, int g) const{ cout<<”
 Humans learn at good   speed.& well”<<endl;}
8. void Work()const { cout<<”
 Human work ….”<<endl;}
9. };
10. class Student:public Human
11. { public:
12. /* students do differently functions. So it overrides base class Learn() function. But base class has Learn() as over loaded function. Therefore balance two overloaded functions are lost to Student.*/
13. void Learn(){ cout<<”
 Students strive to learn professional subjects…”<<endl;}
14. };
15. void main()
16. { Human hum; // object of base class
17. Student std; // object of derived class
18. cout<<”
 Object of base class can call all varieties of overloaded function..”<<endl;
19. hum.Learn();
20. hum.Learn(2); // Learn with double speed
21. hum.Learn(2,2); // Learn with good speed and well
22. cout<<”
 Objectof Student….”<<endl;
23. cout<<”
 Student over rides Learn() of base class”<<endl;
24. std.Learn(); //std over ride one of the base class function Learn()
25. cout<<”
 Two other base class over loaded functions Learn(int), Learn(int,int) are lost”<<endl;
26. //std.Learn(2); //lost
27. cout<<”
std can still call an overloaded base class function by explicit call”<<endl;
28. std.Human::Learn(2);
}
/*Output : Object of base class can call all varieties of overloaded function..
Human beings strive to learn : Humans learn at good speed
Humans learn at good speed & well
Objectof Student. : Student overrides Learn() of base class
Students strive to learn professional subjects
Two other base class overloaded functions Learn(int), Learn (int,int) are lost
std can still call an overloaded base class function by explicit call
Humans learn at good speed */

12.7 Virtual Functions

If function is declared as virtual function in base class, then we can execute an overriding function with the same name in the derived class with a pointer to base class. This means that we have

Inheritance relation available. Ex Student is a Human
Pointer to base class must be declared and memory obtained from
Heap.
Ex Human * ptr = new Student; This is a valid assignment since Student is a Human.

With a pointer to base class we can access all the member data and functions of derived class. But for this magic to work we have to declare the base class functions that are going to be overridden in derived class as virtual function like this

In base class
virtual void Work() const { cout<<”
 Human work ……base class.”;}
In derived class
void Work()const { cout<<”
 Students work in
Laboratories..”<<endl;}

We can, in addition call base class functions which have been normally overridden and requires that an exclusive call has to be made like std.Human::Work(); with a statement shown: cout<< ptr->GetRollNo(); We have shown all the above concepts are working in our next example:

 

Example 12.6:    inherit5.cpp Virtual Functions

//inherit5.cpp Virtual Functions : declare a base class called Human and a
//derived classes called Student
1. #include<iostream>
2. using namespace std;
3. enum CAT { BTECH,MBA,MCA,MSC}; // Category of student
4. class Human
5. {public:
6. Human():idNo(0),name(“Noname”)
7. {cout<<”
Human constructor..”<<endl;} //Base constructor
8. ~Human(){cout<<”
Human destructor..”<<endl;} // base destructor
9. // Public functions
10. void Learn()const{ cout<<”
 Human beings strive to learn …”
<<endl;}
11.virtual void Work()const { cout<<”
 Human work ….”<<endl;}
12. protected: int idNo; char *name;
13. };
14. class Student:public Human
15. { public:
16. Student() {cout<<”
 Student constructor..”<<endl;}
17. ~Student(){}; // Default destructor
18. // functions over ride base class
19. void Learn(){ cout<<”
 Students work at college laboratories…”<<endl;}
20. // Students own function
21. void UseNet(){ cout<<”
 Students use internet for advancement…”<<endl;}
22. // over riding of base class virtual function
23. void Work(){ cout<<”
 Students strive to learn professional subjects
”;}
24. private:
25. // kept empty purposely to make understanding of the program easy
26. };
27. void main()
28. {Human *pstd = new Student;
29. cout <<”
 Calling overriding function Learn()…”<<endl;
30. cout<<”
Though object is derived class as the pointer is to base class
”;
31. cout<<”
 you can see its base class Learn() that is accessed”<<endl;
32. pstd->Learn();
33. cout <<”
calling a virtual function with pointer to base class..”<<endl;
34. cout<<”
Though pointer is to base class , because its virtual function”<<endl;
35. cout<<”
 you can access derived class function..”<<endl;
36. pstd->Learn();
37. }
 /*Output: Human constructor..
 Student constructor.. Calling over riding function Learn()
 Though object is derived class as the pointer is to base class
 you can see its base class Learn() that is accessed
 Human beings strive to learn
 calling a virtual function with pointer to base class..
 Though pointer is to base class, because its virtual function
 you can access derived class function..
 Human beings strive to learn */
Line No. 11: human declares a virtual function learn() to be overridden by derived classes
Line No. 23: Derived class overrides base class virtual function.
Line No. 28: Human *pstd = new Student; The object is new student on the heap memory.
  But the pointer is to base class Human.

12.8 Multiple Virtual Functions

The concept of virtual function can be extended to cover multiple virtual functions. For example, base class can define a virtual function and there can be several derived classes with their own implementations. Depending on the implementation chosen by the user, virtual function pointer can invoke the particular implementation by the derived class. The situation diagram is shown in Figure 12.3.

 

Two derived classes

 

Figure 12.3 Two derived classes

 

 

Example 12.7:    inherit6.cpp Multiple Virtual Functions

1. //Example 12.6 inherit6.cpp multiple virtual functions
2. //declare a base class called Human and two derived classes called Student and Athlete
3. #include<iostream>
4. using namespace std;
5. class Human
6. {
7. public:
8.    Human():idNo(0){} //Base constructor
9.    ~Human(){} // base destructor
10.   // Public functions
11.   virtual void Work()const { cout<<”
 Human work
   ….”<<endl;}
12. protected:
13. int idNo;
14. };
15. class Student:public Human
16. {public:
17. // Own implementation of virtual function Work()
18. void Work()const{ cout<<”
 Students work at college labs..”<<endl;}
19. };
20. class Athlete:public Human
21. {public:
22. // Athletes Own implementation of virtual function Work()
23. void Work()const{ cout<<”
Athletes workout at Gym after study hour
”;}
24. };
25. void main()
26. { Human *hum[2]; // array of pointers to base class
27. Human *ptr; //pointer to base class
28. int i=0;
29. for ( i=0;i<3;i++)
30.     { if(i==1)
31.     ptr=new Student;
32.     else
33.     {if(i==2)
34.     ptr=new Athlete;
35.     else
36.     ptr=new Human;
37.     }
38. hum[i]=ptr;
39. } // end of while
40. for ( i=0;i<3;i++)
41. hum[i]->Work();
42. }
/*Output Human work ….
Students work at college laboratories…
Athletes workout at college Gym after study hours…*/
Line No. 26: Human *hum[2]; // array of pointers to base class.
Line No. 27: Is a pointer to base class.
Line No. 31, 34 & 36: Produces object of new Student, or new Athlet, or new Human depending on if else statements
Line No. 38: allocates pointer to hum[i] and Line No. 40 & 41 run a loop to display hum[i]->work()

12.9 Virtual Destructors: Why and How?

In inheritance relation, we know that a Student is Human. Therefore, we can pass a pointer to derived class instead of pointer to base class. Now when we try to delete the object, the derived class destructor should be called first, which in turn calls the base class destructor. For this to happen, the base class destructor must be declared as virtual. Note that the constructor cannot be declared as virtual.

12.10 Hybrid Inheritance with Multiple Inheritances

In some situations, single inheritance is not sufficient and leads to ambiguity. Consider the example presented in Figure 12.4.

 

Hybrid inheritance

 

Figure 12.4 Hybrid inheritance

 

A Student works at college laboratories and an Athlete works out at the Gym after college hours. But let us say the recruiting companies need a Professional who works at collage laboratories and also takes keen interest in Gym and sports. We need a professional who inherits Work() of Students and also Work() of Athlete on requirement. In addition, the Professional must retain all the basic qualities of Human (shown as dotted arrow).

Multiple inheritance is deriving a class from more than one base class. Also notice in the figure that both Student and Athlete have the same base class. This type of base class is called virtual base class because though there is only one base class common to both derived classes, each of the derived classes feels it has its own base class.

12.11 Virtual Inheritance

Refer to Figure 12.4 once again. The Professional is deriving properties and qualities both from Student and Athlete depending on the need. In order to facilitate inheritance of properties, functions and member data selectively from Student and Athlete, we need to declare these two classes as virtual inheritance from the base class. This concept is illustrated in our next example. The example we have chosen is that companies want to select professionals who are good students and good athletes and good humans. Accordingly, we have introduced fields and variables

enum OKAY{FALSE,TRUE}; // eligible for selection or not.
enum DIV { DISTINCTION,FIRST, SECOND, NATIONAL, STATE, COLLEGE};
for recoding achievements of athletes.
Num or n no of companies willing to give weightage to all round
development

 

Example 12.8:    inherit7.cpp Virtual Inheritance

1. #include<iostream>
2. using namespace std;
3. enum CAT { BTECH,MBA,MCA,MSC}; // Category of student
4. enum BAT { ATHLETE,SPORTS};
5. enum DIV { DISTINCTION,FIRST,SECOND ,NATIONAL, STATE, COLLEGE};
6. // Division obtained by Students
7. enum OKAY{FALSE,TRUE}; // eligible for selection or not
8. class Humans
9. {public:
10. Humans(int n):idNo(n)
11. {cout<<"
 default Humans constructor.."<<endl;} //Base constructor
12. virtual ~Humans(){cout<<"
Humans destructor.."<<endl;} //
base destructor
13. // Public functions
14. virtual int GetId()const{return idNo;}
15. virtual void SetId(int n) { idNo=n;}
16. protected:
17. int idNo;
18. };
19. class Student:virtual public Humans
20. { public:
21. Student(CAT cat , DIV d , int num);
22. virtual ~Student(){}; // Default destructor
23. // students do differently functions
24. virtual void Learn()const{ cout<<”
 Students learn relevant courses
”;}
25. virtual void Work()const{ cout<<”
 Students worked Industry programs
”;}
26. virtual CAT GetCAT() const { return stcat;}
27. virtual void SetCAT(CAT c) { stcat=c;}
28. virtual DIV GetDIV() const { return division;}
29. virtual void SetDIV ( DIV d) { division = d;}
30. protected:
31.     CAT stcat; // students category
32.     DIV division; // division Distinction/first class etc
    obtained
33. };
34. Student::Student(CAT cat , DIV d , int idnum):
35.     Humans(idnum),stcat(cat), division(d)
36.     { cout<<”
 Students constructor..”<<endl;}
37. class Athlet:virtual public Humans
38. { public:
39. Athlet(CAT cat , DIV d , OKAY ok , int idnum);
40. virtual ~Athlet(){}; // Default destructor
41. virtual void AtLearn()const{ cout<<”
 Athlets learn subjects & sports
;}
42. virtual void AtWork()const{ cout<<”
 Athlets worked at lab and GYM
”;}
43. virtual void Play() const{ cout<<”
 Athlets can play games and events
”;}
44. virtual CAT GetCAT() const { return stcat;}
45. virtual void SetCAT(CAT c) { stcat=c;}
46. virtual DIV GetDIV() const { return division;}
47. virtual void SetDIV ( DIV d) { division = d;}
48. virtual OKAY GetOKAY() const { return qualified;}
49. virtual void SetOKAY ( OKAY q) { qualified = q;}
50. private:
51.     CAT stcat;
52.     DIV division; // national/state/district/college
53.     OKAY qualified;
54. };
55. Athlet::Athlet(CAT cat , DIV d , OKAY ok, int idnum):
56. Humans(idnum),stcat(cat),division(d),qualified(ok)
57. {cout<<”
 Athlet constructor..”<<endl;}
58. class Professional : public Student , public Athlet
59. { public:
60. Professional(CAT cat , DIV d, OKAY q ,int idnum , int n); ~Professional(){cout<<”
 Professionals destructor..”<<endl;}
61. // n is no of companies giving weightage to all round development
62. virtual GetNum() const { return num;}
63. //num : these are companies willing to give weightage to sports
64. virtual DIV GetDIV() const { return Student::division;}
65. void AtLearn() const { Learn();} // Learn subjects like students
66. void AtWork() const { Work();} // Work in Laboratories like Students
67. private:
68. int num ; //Number of companies who are willing to give weightage to sports
69. };
70. Professional::Professional(CAT cat , DIV d, OKAY q ,int idnum, int n):
71. Student(cat,d,num),Athlet(cat,d,q,idnum),Humans(idnum),num(n)
72. { cout<<”
 Professionals constructor..”<<endl;}
73. void main()
74. {Professional *ptr = new Professional(BTECH,FIRST,TRUE,50595,100);
75. int rollNo = ptr->GetId();
76. ptr->Learn();
77. //Though we call AtLearn() of Athlet , it will call learn() of Student.
78. //We want student to be sound in Knowledge.
79. ptr->AtLearn();
80. ptr->Play(); // play like an athlete
81. cout<<"
 No of companies allocating weightage to all round personality :"<<ptr->GetNum()<<endl;
82. cout<<"
 Division obtained by the professional :"<<ptr->GetDIV()<<endl;
83. cout<<"
 The selected Professional is : "<<rollNo<<endl;
84. delete ptr;
85. }
/*Output : default Humans constructor..
Students constructor.. : Athlet constructor..: Professionals constructor..
Students learnt Industry relevant courses: Students learnt Industry relevant courses
Athletes can play games and participate in events
No. of companies allocating weightage to all round personality: 100
Division obtained by the professional: 1
Companies tion The selected Professional is: 50595
Professionals destructor..
Humans destructor*/
Line No. 19 & 37: are statements showing Student and Athlete using virtual inheritance form single base class Human.
Line No. 24 & 29: Student declares virtual functions Learn() and Work() so that they can be inherited by Professional if he needs them. Similarly, Line No. 41 to 49 define virtual functions for Athlete class.
Line No. 12, 22, & 40: are virtual destructors.
Line No. 70 & 71: Professional::Professional(CAT cat, DIV d, OKAY q, int idnum, int n) Student(cat,d,num), Athlet(cat,d,q,idnum), Humans(idnum), num(n) are for constructor for Professional. Observe that Student, Athlet and Human constructors are called in turn to create an object called Professional
Line No. 76: ptr->AtLearn(); Though we call AtLearn() of Athlet , it will call learn() of Student. We want student to be sound in Knowledge.

12.12 Run-time Polymorphism and Dynamic Binding

Inheritance solves the problem of reusability. That is derived class can access all the data members and function members of base class that are declared as protected. We have also learnt that derived class can override the functions defined in base class. Further, we have seen while dealing with virtual functions that with a pointer to base class we can call the derived class object

Human *ptr=new Student;

Combining the above two features C++ gives us a powerful tool, called run-time polymorphism and dynamic binding. What this feature means to the programmer is that with a pointer to base class, we can decide at run-time to call a particular derived classes overriding function. In other words, we can bind the overriding function from several of the derived classes, with pointer to base class.

12.13 Abstract Data Types (ADTs)

The features described above, namely, run-time polymorphism and dynamic binding will allow us to define a base class with virtual functions with no implementation (called pure virtual functions) or with dummy functionality just to indicate to the user that implementation is by derived class. These classes are called abstract data types because they hide the implementation.

We will declare a base class called Shape. You will appreciate Shape has no definite shape, no defined area, perimeter or specific draw routine. We will derive classes like Circle and Square and provide the solid implementation of these virtual functions. Solid means all virtual functions will be implemented in each of the derived class. The concepts discussed are at work in our next example.

 

Example 12.9:    inherit8.cpp ADT – Run-time Polymorphism and Dynamic Binding

1. #include<iostream>
2. using namespace std;
3. const double PI=3.14159;
4. class Shape
5. { public:
6. Shape(){};
7. ~Shape(){}
8. virtual double ComputeArea()
9. {cout<<”
 Shape has no definite Area “<<endl;return 0.0;}
10. virtual double ComputePerimeter()
11. {cout<<”
 Shape has no definite Area “<<endl; return 0.0;}
12. virtual void DrawShape() {}};
13. class Circle: public Shape
14. {public: Circle(double r):radius(r){};
15. ~Circle(){}; // Default destructor
16. // Circles do functions differently
17. double ComputeArea()
18. {cout<<"
 Circle implementation of ComputeArea "<<endl;
19. return PI*radius*radius; }
20. virtual double ComputePerimeter()
21. {cout<<"
 Circle implementation of ComputePerimeter <<endl;
22. return 2*PI*radius; }
23. virtual void DrawShape() {cout<<"
 Circle Draw code here" <<endl;}
24. private:double radius;
25. };
26. class Square: public Shape
27. {public: Square(double r):side(r){};
28. ~Square(){}; // Default destructor
29. // Squares do functions differently
30. double ComputeArea()
31. {cout<<"
 Square implementation of ComputeArea "<<endl;
32. return side*side; }
33. virtual double ComputePerimeter()
34. {cout<<"
 Square implementation of ComputePerimeter "<<endl;
35. return 4*side; }
36. virtual void DrawShape() {cout<<"
 Square Draw code here"<<endl;}
37. private:double side;
38. };
39. void main()
40. { int choice;
41.      Shape *ptr; // pointer to base class
42.      while(choice!=3)
43. {    cout<<"
 1 : Circle 2 : Square 3: Exit .. :";
44.      cin>>choice;
45.      switch(choice)
46.      { case 1 : ptr = new Circle(2.0); break;
47.      case 2 : ptr= new Square(5.0); break;
48.      case 3 : exit(0);
49.      default: cout<<"
 wrong choice. Try Again.."<<endl; continue;
50.      }
51.      // Function Polymorphism and Dynamic Binding at work
52.      ptr->ComputeArea(); // call to derived class function
53.      ptr->ComputePerimeter();ptr->DrawShape();
54.     }//end of while
55.     }//end of main
/*Output 1 : Circle 2 : Square 3: Exit .. :1
Circle implementation of ComputeArea
Circle implementation of ComputePerimeter
Cirle Draw code here
1 : Circle 2 : Square 3: Exit .. :2
Square implementation of ComputeArea
Square implementation of ComputePerimeter
Square Draw code here
1 : Circle 2 : Square 3: Exit .. :3 *//*output :1 : Circle 2 : Square 3: Exit .. :1
Circle implementation of ComputeArea
Circle implementation of ComputePerimeter
Cirle Draw code here
1 : Circle 2 : Square 3: Exit .. :2
Square implementation of ComputeArea
Square implementation of ComputePerimeter
Square Draw code here
1 : Circle 2 : Square 3: Exit .. :4
wrong choice. Try Again..
1 : Circle 2 : Square 3: Exit .. :3 */

12.14 Pure Virtual Functions

Sometimes we will need situations wherein base class should not have any solid implementation. Like we did not achieve anything in ComputeArea() or DrawShape() functions in base class. They are simply tools to create pointer to derived class functions wherein all virtual functions are implemented. In such cases, it is better to use pure virtual functions.

virtual double ComputeArea()=0;
virtual void DrawShape()=0;

By declaring a function in base class, we are telling the compiler that implementations are in derived class. Note that if a base class has pure virtual functions, we cannot create an object of base class at all. Also all pure virtual functions must be implemented in derived class.

But if you have some common functionality which every derived class must implement, then repeating the code at each of the derived classes defeats the purpose of reusability. Thankfully, you can include such common code in the base class Shape and, for solid implementations, use derived class DrawShape() and on completion revert to base class for undertaking common functionality. We provide implementation of pure virtual function in the example that follows:

 

Example 12.10:    inherit9.cpp ADT – Run-time Polymorphism and Dynamic Binding

1. #include<iostream>
2. using namespace std;
3. const double PI=3.14159;
4. class Shape
5. {public: Shape(){};
6.    ~Shape(){}
7.    virtual double ComputeArea()=0; //pure virtual function
8.    virtual double ComputePerimeter() =0;
9.    virtual void DrawShape()=0;
10. };
11. // We will implement DrawShape (), though it is a pure virtual Function
12. // to include common functionality of all the derived functions
13. void Shape::DrawShape()
14. {cout<<”
 Completion of DrawShape() mechanism from derived class…”<<endl; }
15. class Circle: public Shape
16. {public: Circle(double r):radius(r){};
17.    ~Circle(){}; // Default destructor
18.    // Circles do functions differently
19.    double ComputeArea()
20.    {cout<<"
 Circle implementation of ComputeArea "<<endl;
21.    return PI*radius*radius;}
22.    double ComputePerimeter()
23.    {cout<<"
 Circle implementation of ComputePerimeter "<<endl;
24.    return 2*PI*radius;}
25.    void DrawShape()
26.    {cout<<"
 Circle Draw code here"<<endl;
27.    Shape::DrawShape();} // call to base class to finish common functionality
28. private: double radius;
29. };
30. class Square: public Shape
31. {public: Square(double r):side(r){};
32.    ~Square(){}; // Default destructor
33.    // Square implements functions differently
34.    double ComputeArea()
35.    {cout<<"
 Square implementation of ComputeArea "<<endl;
36.    return side*side;}
37.    double ComputePerimeter()
38.    {cout<<"
 Square implementation of ComputePerimeter "<<endl;
39.    return 4*side;}
40.    void DrawShape()
41.    {cout<<"
 Square Draw code here"<<endl;
42.    Shape::DrawShape(); } // call to base class to finish common functionality
43. private:double side;
44. };
45. void main()
46. {int choice;
47. Shape *ptr; // pointer to base class
48. while(choice!=3)
49. {cout<<"
 1 : Circle 2 : Square 3: Exit .. :";
50.    cin>>choice;
51.    switch(choice)
52.    { case 1 : ptr = new Circle(2.0); break;
53.    case 2 : ptr= new Square(5.0); break;
54.    case 3 : exit(0);
55.    default: cout<<"
 wrong choice. Try Again.."<<endl; continue;
56.    }
57.    ptr->ComputeArea(); ptr->ComputePerimeter(); ptr->DrawShape();
58. }//end of while
59. }
/*Output 1 : Circle 2 : Square 3: Exit .. :1
Circle implementation of ComputeArea
Circle implementation of ComputePerimeter
Cirle Draw code here
Completion of DrawShape() mechanism from derived class…
1 : Circle 2 : Square 3: Exit .. :2
Square implementation of ComputeArea
Square implementation of ComputePerimeter
Square Draw code here
Completion of DrawShape() mechanism from derived class…
1 : Circle 2 : Square 3: Exit .. :3

12.15 Summary

  1. Reusability is the main reason why inheritance has been included as an important concept of OOP language.
  2. Inheritance specifies is type of relation.
  3. A derived class can inherit public or private or protected.
  4. If inheritance is public then public and protected members of base class remain public and protected in derived class.
  5. If inheritance is protected, the public and protected members become protected members.
  6. If inheritance is private, the public and protected members become private members.
  7. Single inheritance is when a derived class inherits only from one base class.
  8. Multiple inheritance is when a derived class inherits from multiple base classes.
  9. Hierarchical inheritance is when many derived classes inherit from a single base class.
  10. Multilevel inheritance is when a derived class inherits from a class which has been inherited from another class.
  11. Hybrid inheritance is when a derived classes inherits from multiple base classes and they in turn are derived from a single base class.
  12. In hybrid inheritance, ambiguity may arise and to resolve the ambiguity use explicit call with scope resolution operator :: or declare the base classes as virtual. This is called virtual inheritance.
  13. When a derived class overrides a base class function and if the base class function has been overloaded three times, then except for the function that is overridden, the other two overloaded functions are hidden and not available.
  14. If the function is declared as virtual function in base class, then we can execute an overriding function with the same name in the derived class with a pointer to the base class.
  15. In multiple virtual functions, the base class defines a virtual function and there can be several derived classes with their own implementations.
  16. Destructors can be virtual but constructors cannot be virtual.
  17. Run-time polymorphism means that we can bind the overriding function from several of the derived classes, with pointer to base class.
  18. Classes are called abstract data types because they hide the implementation. A base class with virtual functions with no implementation (called pure virtual functions) or with dummy functionality indicates to the user that implementation is by derived class.
  19. A pure virtual function means a base class should not have any solid implementation, but contains only names of the functions. For example: virtual void DrawShape()=0; Pure virtual functions are simply tools to create pointer to derived class functions.

Exercise Questions

Objective Questions

  1. Inheritance specifies -------- type of relation.
    1. has
    2. was
    3. is
    4. segregation
  2. In public inheritance, public implies derived class can inherit
    1. Only public variable
    2. Only public functions
    3. Both member functions and member data
    4. (d) None of member functions and member data
  3. If a function has an object it has access to
    1. All public member functions and data
    2. All private member functions and data
    3. All protected members and data from objects from which they derive
    1. i
    2. i and ii
    3. ii and iii
    4. i, ii and iii
  4. Public function of a derived class can access all the protected data of base class     TRUE/FALSE
  5. When you create the object for the derived class, the constructor for derived class is called first.     TRUE/FALSE
  6. When an object belonging to derived class has to be removed, the base class destructor will be called first.     TRUE/FALSE
  7. When a derived class overrides a base class overloaded function, the object of derived class can get access to
    1. Only overridden function of derived class.
    2. All the overloaded functions of base class.
    3. All the overridden functions of derived class.
    1. i only
    2. ii only
    3. i and ii
    4. i and iii
  8. In C++ pointer to base class can be assigned to derived class.     TRUE/FALSE
  9. For run-time polymorphism and dynamic binding to work the following are required: Pointer to base class
    1. Inheritance relation
    2. Function to be declared as virtual
    3. Function to be overridden in derived class
    1. i and ii
    2. i, ii and iii
    3. i, ii, iii and iv
    4. NOT i, ii, iii and iv
  10. What is the name of the relation depicted in the picture?

     

    image

     

    1. Inheritance
    2. Virtual base class
    3. Multiple inheritance
    4. All of a, b, c
  11. What is the name of the relation depicted in the picture?

     

    image

     

    1. Virtual base class
    2. Multiple inheritance
    3. Inheritance
    4. b and c
  12. Pure virtual functions declaration in base class means
    1. No implementation in base class only name
    2. Common to all derived classes implementation can be included in base class
    3. Derived classes must implement all the pure virtual functions.
    1. Not i, ii and iii
    2. i, NOT ii and iii
    3. i, ii and iii
    4. i, ii and NOT iii
  13. Pure virtual function means
    1. Object to class that has pure virtual function cannot be declared.
    2. Derived class must define all pure virtual function in its class.
    3. Virtual r/t function name() {};
    4. Virtual r/t function name ()=0;
    5. Pure virtual r/t function name ()=0;
    1. i, ii, not iii, iv and not v
    2. i, ii and iii
    3. i, ii and v
    4. i, ii and iv
  14. Destructor need not be virtual if a class has virtual functions     TRUE/FALSE
  15. Constructor of class having virtual function can be virtual     TRUE/FALSE
  16. ADT are so-called because
    1. They hide implementation
    2. They bind member functions of derived class dynamically at run-time.
    3. They have abstract data
    1. i
    2. ii
    3. iii
    4. i and ii
  17. What is the name of the relation depicted in the picture?

     

    image

     

    1. Hybrid inheritance
    2. Virtual base class
    3. Multiple inheritance
    4. All of a, b and c
  18. What is the name of the relation depicted in the picture?

     

    image

     

    1. Hierarchical inheritance
    2. Virtual base class
    3. Multiple inheritance
    4. a, b and c
  19. Protected members in a base class can be accessed
    1. Only in derived class
    2. Only in base class
    3. Both i and ii (iv) None
  20. In public inheritance, public members become public in derived class.     TRUE/FALSE
  21. In private inheritance, the inherited members can further be passed on to derived classe by class.     TRUE/FALSE
  22. In protected inheritance, public members & protected members retain their visibility in derived class.     TRUE/FALSE

    Short-answer Questions

  23. What is public inheritance? What is private inheritance? On what occasions do you use public or private inheritance?
  24. What are the types of inheritance?
  25. What is virtual inheritance?
  26. Can constructors be virtual? Why or why not?
  27. Can destructors be virtual? Why or why not?
  28. Explain base class over riding.
  29. Explain multiple virtual functions.

    Long-answer Questions

  30. Discuss the access specifiers and the visibility in inheritance relationship.
  31. Compare is a and has a relationship with suitable examples.
  32. Distinguish between overloading and base class overriding. What is base class function hiding?
  33. What are virtual functions? How are they different from pure virtual functions?
  34. Explain run-time polymorphism and dynamic binding.
  35. What are abstract classes? How are they useful in achieving reusability in OOPs?
  36. Explain how hybrid inheritance leads to ambiguity and this ambiguity can be resolved.

    Assignment Questions

  37. What does inheritance mean in C++? What are the different types of inheritances? Give examples for each type.
  38. What is a virtual function? Why do we need virtual functions? What are the rules for virtual function implementation?
  39. What is an abstract class? Why do we need abstract classes? What are the rules governing virtual base class? Implement a program covering the above aspects.
  40. Are friendship and inheritance contradicting in their roles? When do you use friend functions and when do you use inheritance.
  41. Containment and inheritance have been introduced to achieve reusability. Bring out the similarities and differences through examples.
  42. Are ADT and pure virtual functions one and the same or are they different? Explain with suitable examples.
  43. Bring out the differences in constructor invocation in case of nested classes and inherited classes.
  44. The relationships in a bank are shown below. The class diagram shown also indicates the functions and member data. The additional rules are Type of account : current and savings

    Minimum Balance: Rs 5000/– for current and Rs 1000/– for savings.

    Penalty: Rs 100/– if the balance falls below and also makes the account inactive.

     

    image

     

    The functionality of banking system to include

    Update transaction of deposited amount and display Transaction details.

    Compute annual interest compounded twice at 10% per annum of interest.

Solutions to Objective Questions

  1. c
  2. c
  3. d
  4. True
  5. False
  6. False
  7. d
  8. True
  9. c
  10. c
  11. b
  12. c
  13. a
  14. False
  15. False
  16. d
  17. d
  18. a
  19. c
  20. True
  21. False
  22. True
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.136.142