Unit 3
• 3.1 Inheritance :
• Introduction , Derived classes, single Inheritance, inheriting private
members, Member declaration: protected, public and private ,
member accessibility and visibility modes
• 3.2 Types of inheritance: Single, Multilevel, Multiple, Hierarchical,
Hybrid, Multipath inheritance, Virtual base classes, Abstract
Classes, Constructors in derived classes.
Introduction
• Reusability is yet another important feature of OOP.
• Fortunately, 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.
• This is basically done by creating new classes, reusing the properties
of the existing ones.
• 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, the traits of one class may be inherited by more than
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.
Defining Derived Classes
• A derived class is defined by specifying its relationship with the
base class in addition to its own details .
• In general form of defining a derived class is:
• 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.
• When a base class is privately inherited by a derived 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.
Single Inheritance
• Let us consider a simple example to illustrate inheritance.
• Program 8.1 shows a base class B and a derived class D.
• The class B contains
– one private data member, one public data member,
and
– three public member functions.
• The class D contains
– one private data member and
– two public member functions.
• The class D is a public derivation of the base class B.
• Therefore, D inherits all the public members of B and retains their
visibility.
• Thus a public member of the base class B is also a public member of
the derived class D.
• The private members of B cannot be inherited by D.
• The class D, in effect, will have more members than what it contains
at the time of declaration as shown in Fig. 8.2.
• The program illustrates that the objects of class D have access to all the public
members of B.
• Let us have a look at the functions show_a( ) and mul( ):
void show_a()
{
cout « "a = " « a « "\n";
}
void mul()
{
c = b * get_a() ; // c = b * a
}
• Although the data member a is private in B and cannot be inherited, objects
of D are able to access it through an inherited member function of B.
• Let us now consider the case of private
derivation.
• The membership of the derived class D is shown in Fig. 8.3.
• In private derivation, the public members of the base class
become
private members of the derived class.
• Therefore, the objects of D can not have direct access to the
public member functions of B.
• The statements such as will not work.
– d.get_ab(); //get_ab() is private
– d.get_a(); //so also get_a()
– d.show_a(); // and show_a()
• However, these functions can be used inside mul()and display() like the
normal functions as shown below:
void mul()
{
get_ab();
c = b * get_a();
void display()
{
show_a(); //outputs value of 'a'
cout «"b = " « b « ''\n''
« "c = " « c « ''\n\n'';
Program 8.2 incorporates these modifications for private derivation. Please
compare this with Program 8.1.
• Suppose a base class and a derived class define a function of the
same name.
• What will happen when a derived class object invokes the function?
• In such cases, the derived class function supersedes the base
class definition.
• The base class function will be called only if the derived class does
not redefine "the function.
Making A Private Member
•
Inheritable
What should we do if the private data needs to be inherited by a derived
class?
• This can be accomplished by modifying the visibility limit of the private
member by making it public.
• This would make it accessible to all the other functions of the program, thus
eliminate the advantage of data hiding.
• C++ provides a third visibility modifier, protected, which serve 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:
• 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).
• Figure 8.4 is the pictorial representation for the two levels of derivation;
• Table 8.1 summarizes how the visibility of members undergo
modifications when they are inherited.
• The keywords private, protected, and public may appear in any
order and in any number of times in the declaration of a class.
• is a valid class definition.
• Now lets review the access control to the private and protected members of
a class.
• What are the various functions that can have access to these members?
They could be:
– 1. A function that is a friend of the class.
– 2. A member function of a class that is a friend of the class.
– 3. A member function of a derived class.
• While the friend functions and-the member functions of a friend class can
have direct access to both the private and protected data, the member
functions of a derived class can directly access only the protected data.
• However, they can access the private data through the member functions
of
the base class.
• Figure 8.5 illustrates how the access control mechanism works in various
situations.
Multilevel Inheritance
• It is not uncommon that a class is derived from another derived class
as shown in Fig. 8.6.
• The class A serves as a base class for the derived class B which 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:
• 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:
• The class result, after inheritance from 'grandfather' through
'father', would contain the following members:
• The inherited functions put_number() and put_marks( ) can be used
in the definition of display( ) function:
• Here is a simple main( ) program:
• This will display the result of student!. The complete program is shown
in Program 8.3
Multiple Inheritance
• A class can inherit the attributes of two or more classes as shown in Fig.
8.7. 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 and the
intelligence of another.
• The syntax of a derived class with multiple base classes is as follows:
• where, visibility may be either public or private. The base classes are
separated by commas
• The derived class P, as declared above, would, in effect, contain all the
members of M and N in addition to its own members as' shown
below:
Hierarchical Inheritance
• We discussed so far how inheritance can be used to modify a class
when it did not satisfy the requirements" of a particular problem on
hand.
• Additional members are added through inheritance to extend the
capabilities of a class.
• Another interesting application of inheritance is to use it as a support
to the hierarchical design of a program.
• Many programming problems can be cast into a hierarchy where certain
features of one level are shared by many others below that level.
• As an example, Fig. 8.8 shows a hierarchical classification of students
in a university.
• Another example could be the classification of accounts in a
commercial bank as shown in Fig. 8.9.
• All the students have certain things in common and, similarly, all
the accounts possess certain common features.
• In C++, such problems can be easily converted into class hierarchies.
• The base class will include all the features that are common to
the subclasses.
• A subclass can be constructed by inheriting the properties of the
base class.
• A subclass can serve as a base class for the lower level classes and so
on.
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 discussed in section 8.5.
• 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. 8.10.
• The result will have both the multilevel and multiple inheritances and
its declaration would be as follows:
Virtual Base Classes
• We have just discussed a situation which would require the use of both
the multiple and multilevel inheritance.
• Consider a situation where all the three kinds of inheritance, namely,
multilevel, multiple and hierarchical inheritance, are involved.
• This is illustrated in Fig. 8.11.
• The 'child' has two direct base classes 'parent1 ' and 'parent2'
which themselves have a common base class ,grandparent' .
• The' child' inherits the traits of 'grandparent' via two separate paths.
It can also inherit directly as shown by the broken line.
• The 'grandparent’ is sometimes referred to as indirect base class.
• Inheritance by the 'child' as shown in Fig. 8.11 might pose some problems.
• All the public and protected members of 'grandparent' are inherited
into 'child' twice, first via 'parent1' and again via 'parent2'.
• This means, 'child' would have duplicate sets of the members inherited
from
'grandparent' .
• This introduces ambiguity and should be avoided.
• The duplication of inherited members due' to these multiple paths
can be avoided by making the common base class (ancestor class) as
virtual base class while declaring the direct or intermediate base
classes as shown below:
• When a class is made a virtual base class, c++ takes necessary care to
see that only one copy of that class is inherited, regardless of how many
inheritance paths exist between the virtual base class and a derived class.
Note that the keywords virtual and public may be used in either order.
• For example., consider again the student results processing
system discussed in section 8.8.
• Assume that the class sports derives the roll_number from the
class, student.
• Then, the inheritance relationship will be as shown in Fig. 8.12.
• A program to implement the concept of virtual base class is illustrated
in Program 8.6.
Abstract Classes
• An abstract class is one that is not used to create objects.
• An abstract class is designed only to act as a base class (to be
inherited by other classes).
• It is a design concept in program development and provides a base
upon which other classes may be built.
• In the previous example, the student class is an abstract class since it
was
not used to create any objects
Constructors In Derived Classes
• As we know, the constructors play an important role in initializing
objects.
• One important thing to note here is that, as long as no base class
constructor takes any arguments, the derived class need not have
a constructor function.
• However, if any base class contains a constructor with one or more
agruments, then it is mandatory for the derived class to have a
constructor and pass the arguments to the base class
constructors.
Constructors In Derived Classes
• Remember, while applying inheritance we usually create objects
using the derived class.
• Thus, it makes sense for the derived class to pass arguments to the
base class constructor.
• When both the derived and base classes contain constructors, the
base constructor is executed first and then the constructor in the
derived class is executed.
• In case of multiple inheritance, the base classes are constructed in the
order in which they appear in the declaration of the derived class.
• Similarly, in a multilevel inheritance, the constructors will be executed
in the order of inheritance.
• Since the derived class takes the responsibility of supplying initial
values to its base classes, we supply the initial values that are
required by all the classes together when a derived class object is
declared.
• How are they passed to the base class constructors so that they can
do their job?
• C++ supports a special argument passing mechanism for
such situations.
• The constructor of the derived class receives the entire list of values as
its arguments and passes them on to the base constructors in the order
in which they are declared in the derived class.
• The base constructors are called and executed before executing the
statements in the body of the derived constructor. –
• The general form of defining a derived constructor is:
• The header line of derived-constructor function contains two
parts separated by a colon(:).
• The first part provides the declaration of the arguments that are
passed to the derived-constructor and the second part lists the
function calls to the base constructors.
• basel (arglistl) , base2(arglist2) ... are function calls to base
constructors basel( ), base2( ) , ... and therefore arglistl, arglist2, ... etc.
represent the actual parameters that are passed to the base
constructors.
• Arglistl through ArglistN are the argument declarations for the
base constructors basel through baseN.
• ArglistD provides the parameters that are necessary to initialize the
members of the derived class.
• A (al, a2) invokes the base constructor A( ) and B(bl, b2) invokes another base
constructor B( ).
• The constructorD( ) supplies the values for these four arguments.
• In addition, it has one argument of its own.
• The constructor D( ) has a total of five arguments.
• D() may be invoked as follows:
• These values are assigned to various parameters by the constructor
D( ) as follows:
• The constructors for virtual base classes are invoked before any
non- virtual base classes.
• If there are multiple virtual base classes, they are invoked in the order
in which they are declared.
• Any nonvirtual bases are then constructed before the derived
class constructor is executed. See Table 8.2.
• Note that beta is initialized first, although it appears second in
the derived constructor.
• This is because it has been declared first in the derived class
header line.
• Also, note that alpba(a) and beta(b) are function calls.
• Therefore, the parameters should not include types.
• C++ supports another method of initializing the class objects.
• This method uses what is known as initialization list in the
constructor function. This takes the following form:
• The assignment-section is nothing but the body of the
constructor function and is used to assign initial values to its
data members.
• The part immediately following the colon is known as the
initialization
section.
• We can use this section to provide initial values to the base
constructors and also to initialize its own class members.
• This means that we can use either of the sections to initialize the
data members of the constructors class.
• The initialization section basically contains a list of
initializations separated by commas.
• Consider a simple example:
• This program will initialize a to 2 and b to 6.
• Note how the data members are initialized, just by using the variable
name followed by the initialization value enclosed in the
parenthesis (like a function call).
• Any of the' parameters of the argument list may be used as the
initialization value and the items in the list may be in any
order.
• For example, the constructor XYZ may also be written as:
• In this case, a will be initialized to 5 and b to 2.
• Remember, the data members are initialized in the order of
declaration, independent of the order in the initialization list.
• This enables us to have statements such as
• Here a is initialized to 2 and b to 6.
• Remember, a which has been declared first is initialized first and then
its value is used to initialize b.
• However, the following will riot work:
• because the value of b is not available to a which is to be initialized first.
• The following statements are also valid:
• We can omit either section, if it 'is not needed.
• Program 8.8 illustrates the use of initialization lists in the base and
derived constructors.
• Note that the argument list of the derived constructor gamma contains
only three parameters a, b and c which are used to initialize the five data
members contained in all the three classes.
MEMBER CLASSES: NESTING OF CLASSES
• Inheritance is the mechanism of deriving certain properties of one
class into another.
• C++ supports yet another way of inheriting properties of one class
into another.
• This approach takes a view that an object can be a collection of
many other objects.
• That is, a class can contain objects of other classes as its members
as shown below:
• All objects of gamma class will contain the objects a and b. This kind of
relationship is called containership or nesting.
• Creation of an object that contains another object is very different than the
creation of an independent object.
• An independent object is created by its constructor when it is declared with
arguments.
• On the other hand, a nested object is created in two stages.
• First, the member objects are created using their respective constructors and
then the other ordinary' members are created.
• This means, constructors of all the member objects should be called before its
own constructor body is executed.
• This is accomplished using an initialization list in the constructor of the
nested class.
• arglist is the list of arguments that is to be supplied when a gamma object is defined.
• These parameters are used for initializing 'the members of gamma.
• Arglist1 is the argument list for the constructor of a and arglist2 is the argument list
for the constructor of b.
• arglistl and arglist2 may or may not use the arguments from arglist.
• Remember, a (arglistl ) and b (arglist2) are function calls and therefore the arguments
do not contain the data types.
• They are simply variables or constants.
• We can use as many member objects as are required in a class.
• For each member object we add a constructor call in the initializer
list.
• The constructors of the member objects are called in the order in
which they" are declared in the nested class.