Inheritance
·
In C++, inheritance is the mechanism by which
one class can inherit the properties of another.
·
When one class is inherited by another, the
class that is inherited is called the base class. The inheriting class is
called derived class.
·
Base class is also known as parent class or old
class. Derived class is also known as child class or new class.
·
Remember constructor never inherits.
·
Structure in C++ also supports inheritance.
Syntax for
inheritance
class base-name
{
…
};
class derived-name :
visibility mode base-name
{
…
};
·
Syntax covers two classes, one is base class and
other is derived class.
·
During derived class definition, notice a colon
(:) followed by visibility mode and then comes base class name. This addition
to derived class definition tells the compiler about linking between two
classes.
·
Members of base class now also consider members
of derived class.
·
Membership category for the base class members
in derived class are defined by visibility mode.
·
Visibility modes are private, protected and
public.
·
In class, when no visibility mode is mentioned,
it is private by default.
·
In structure, when no visibility mode is
mentioned, it is public by default.
Visibility Modes
·
Whatever may the visibility mode, private
members of base class never inherits.
·
When visibility mode is private, all protected and public members of base class become
private members of derived class.
·
When visibility mode is protected, all protected and public members of base class become
protected members of derived class.
·
When visibility mode is public, all protected members of base class become protected
members of derived class and all public members of base class become public
members of derived class.
Consider the
following example
#include<iostream.h>
class A
{
private:
int
a;
protected:
int b;
public:
void
getdata()
{
cout<<”Enter
two numbers”;
cin>>a>>b;
}
void
showdata()
{
cout<<”a=”<<a<<”b=”<<b;
}
};
class B : public A
{
private:
int
m;
protected:
int
n;
public:
void
get()
{
cout<<”Enter
two numbers”;
cin>>m>>n;
}
void
show()
{
cout<<”m=”<<m<<”
n=”<<n;
}
};
void main()
{
B
o1;
o1.a=2; //error: a is
not a member of class B, private members never inherits
o1.b=3;
//error: b is a protected member in class B, so can’t be access
o1.m=4; //error: m is private
member of class B, so can’t be access
o1.n=5; // error: n is protected
member of class B, so can’t be access
o1.getdata(); //correct: as
getdata() is a public member in class B
o1.showdata();
//correct: as showdata() is a public member in class B
o1.get(); //correct: as get() is a public member
in class B
o1.show(); //correct: as show() is
a public member in class B
}
l In
this example, A is a base class and B is derived class.
l Notice
member variables and access specifiers for them. Also observe that the
visibility mode is public during inheritance. This makes all protected members
Protected in derived class and all public members become public members in
derived class.
l Some
of the lines in above program will yield errors, so while executing remove
these lines from main function. Read the comments to understand errors.
l Whenever
we want to extend class definition, we write a new class instead of writing
members in the old class. This new class should be derived class of old one.
Once we created object of child class it contains member variables of child
class as well as parent class. This mechanism is good to support encapsulation.
We should not create more than one object to store information of single
object. By doing inheritance we can create a single object of child class to
store information against variables of parent and child class.
Consider similar
example but visibility mode is protected
#include<iostream.h>
class A
{
private:
int
a;
protected:
int b;
public:
void
getdata()
{
cout<<”Enter
two numbers”;
cin>>a>>b;
}
void
showdata()
{
cout<<”a=”<<a<<”b=”<<b;
}
};
class B : protected A
{
private:
int
m;
protected:
int
n;
public:
void
get()
{
cout<<”Enter
two numbers”;
cin>>m>>n;
}
void
show()
{
cout<<”m=”<<m<<”
n=”<<n;
}
};
void main()
{
B o1;
o1.a=2; //error: a is
not a member of class B, private members never inherits
o1.b=3; //error: b is a protected member in class
B, so can’t be access
o1.m=4;
//error: m is private member of class B, so can’t be access
o1.n=5; // error: n is protected
member of class B, so can’t be access
o1.getdata(); //error: getdata()
is a protected member in class B
o1.showdata();
//error: showdata() is a protected member in class B
o1.get(); //correct: as get() is a public member
in class B
o1.show();
//correct: as show() is a public member in class B
}
Consider another
similar example for visibility mode private
#include<iostream.h>
class A
{
private:
int
a;
protected:
int b;
public:
void
getdata()
{
cout<<”Enter
two numbers”;
cin>>a>>b;
}
void
showdata()
{
cout<<”a=”<<a<<”b=”<<b;
}
};
class B :
private A
{
private:
int
m;
protected:
int
n;
public:
void
get()
{
cout<<”Enter
two numbers”;
cin>>m>>n;
}
void
show()
{
cout<<”m=”<<m<<”
n=”<<n;
}
};
void main()
{
B
o1;
o1.a=2; //error: a is not a member of class B, private
members never inherits
o1.b=3;
//error: b is a private member in class B, so can’t be access
o1.m=4;
//error: m is private member of class B, so can’t be access
o1.n=5;
// error: n is protected member of class B, so can’t be access
o1.getdata(); //correct: getdata()
is a private member in class B
o1.showdata(); //correct: showdata()
is a private member in class B
o1.get();
//correct: as get() is a
public member in class B
o1.show();
//correct: as show() is a public member in class B
}
Advantages of
inheritance
·
Reusability
·
Saves time and efforts
·
Increases program structure which results in
greater reliability.
·
It implements generalization and specialization
Types of inheritance
There are five types of inheritance:
1) Single inheritance
When there is one parent class and one child class
inheriting properties from base class, known as single inheritance.
Syntax:
class Base
{….};
class Derived: visibility mode Base
{….};
2) Multilevel
inheritance
When a child class becomes parent of other class, it
increases level of inheritance and known as multilevel inheritance.
Syntax
class A
{….};
class B: visibility-mode A
{….};
class C: visibility- mode B
{….};
3) Multiple
inheritance
When a child class has more than one parent class, it is
known as multiple inheritance.
Syntax
class A1
{….};
class A2
{….};
class B: visibility- mode A1, visibility-mode A2
{….};
4) Hierarchical
inheritance
When a base class has more than one child classes, it is
known as hierarchical inheritance.
Syntax
class A
{….};
class B1: visibility-mode A
{….};
class B2: visibility- mode A
{….};
5) Hybrid inheritance
A single structure of classes obtained from more than one
type of inheritance is known as hybrid inheritance.
Syntax
class A
{….};
class B1: visibility-mode A
{….};
class B2: visibility- mode A
{….};
class C: visibility-mode B1, visibility-mode B2
{….};
Constructors in
inheritance
l Always
remember constructor never inherits
l 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 arguments, then it is mandatory for the derived
class to have a constructor and pass the arguments to the base class
constructors.
l 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.
l In
multilevel inheritance the constructor will be executed in the order of
inheritance. In case of multiple inheritance the base class are constructed in
the order in which they appear in the declaration of the derived class.
Syntax:
Derived-constructor(arglist1,arglist2,…,arglist
d) :
base1(arglist1), base2(arglist2),…
{
…
… //argument list d is used
here(base constructor’s
… //definition
…
}
Consider the
following example to implement constructors in inheritance
#include<iostream.h>
#include<conio.h>
class A
{
private:
int a;
public:
A()
{
cout<<”\nBase
Class Constructor”;
a=0;
}
void
showa()
{
cout<<”\na=”<<a;
}
};
class B : public A
{
private:
int
b;
public:
B():A()
{
cout<<”\nChild Class Constructor”;
b=0;
}
void
showb()
{
cout<<”\nb=”<<b;
}
};
void main()
{
B
obj;
obj.showa();
obj.showb();
getch();
}
Explanation:
l Constructor
of child class is invoked as soon as we create object of child class B. But
important thing to notice that child class constructor invite parent class
constructor to run parent class constructor before child class constructor.
l So
the output of the above program is
Base Class Constructor
Child Class Constructor
a=0
b=0
l Notice the way child constructor call base class
constructor. It is child class constructor then colon (:) and followed by base
class constructor call.
l If we have base class constructor with arguments then it is
the duty of child class constructor to pass arguments.
l If there is no constructor in base class then child class
constructor calls implicit constructor of base class.
l If there is no constructor in child class and base class
contain default constructor or constructor with no argument then implicit
constructor of child class would call constructor of parent class.
l If there is a parameterized constructor in parent class
then it is must to define a constructor in child class who invokes parent class
constructor by passing correct number of arguments
l We can say execution order of constructor is the order of
inheritance that is from parent most class to child class
Destructor in inheritance
Just like constructors destructors
also non inheritable members. Their execution order is reverse the execution
order of constructors. This means child class destructors executes first and
followed by parent class destructors.
Function Overriding
During inheritance when base class
and derived class both shares a common function name in their respective class
two situations encounters:
First scenario when a function in
derived class has same name as of function in base class with same prototype.
This is called function overriding.
Whenever this function s called
using child class object child class version will be invoked.
To invoke base class version we
need to specify class name and scope resolution operator.
Following example enlighten this
fact.
#include<conio.h>
#include<iostream.h>
class
Base
{
public:
void msg()
{
cout<<” Base Message”;
}
};
class
Derived : public Base
{
public:
void msg()
{
cout<<” Derived Message”;
}
};
void
main()
{
Derived O;
O.msg(); //Derived class msg() executes
O.Base::msg(); //Base class msg() executes
}
Function Hiding
Second scenario is when base and derived class share same
function name but different prototypes. In such case it can not be considered
as function overloading as functions are in different scopes. Here, we say
function hiding.
#include<conio.h>
#include<iostream.h>
class
Base
{
public:
void msg(int k)
{
cout<<” Base Message”<<k;
}
};
class
Derived : public Base
{
public:
void msg()
{
cout<<” Derived Message”;
}
};
void
main()
{
Derived O;
O.msg(); //Derived class msg() executes
O.Base::msg(3); //Base class msg() executes
O.msg(3); //error as derived msg() hides base
msg(int)
}
Virtual base class
A special scenario arises during hybrid inheritance. First
to let us understand problem consider the following example
#include<conio.h>
#include<iostream.h>
class A
{
public:
void fun_a()
{
cout<<”Function of Class A”;
}
};
class B1: public A
{
public:
void fun_b1()
{
cout<<”Function of Class
B1”;
}
};
class B2: public A
{
public:
void fun_b2()
{
cout<<”Function of Class
B2”;
}
};
class C: public B1,
public B2
{
public:
void fun_c()
{
cout<<”Function of Class A”;
}
};
void main()
{
C O1;
O1.fun_c(); //valid
O1.fun_b1(); //valid as publicly inherited
from base B1
O1.fun_b2(); // valid as publicly inherited
from base B2
O1.fun_a(); //error: ambiguity between two copies of function in class C
inherited twice // via class B1 and B2
}
Since function fun_a() of parent most class A is inherited
twice in class C, first via class B1 and second via class B2. This makes two
copies of the same function in child most class C and can not be resolved
function call due to identical prototype. This leads to an ambiguity error.
Solution of the above problem is to make parent most class
as virtual base class of class C. This means class A will now become virtually
parent class of class C, instead of grant parent.
During definition of intermediate base classes B1 and B2, we
mention keyword virtual to make parent class A virtual base class of child
class of B1 and B2. Now only one copy of function fun_a() will be available for
class C.
Following example illustrates syntactical part of virtual
base class:
#include<conio.h>
#include<iostream.h>
class A
{
public:
void fun_a()
{
cout<<”Function of Class A”;
}
};
class B1: virtual public
A
{
public:
void fun_b1()
{
cout<<”Function of Class
B1”;
}
};
class B2: public virtual
A
{
public:
void fun_b2()
{
cout<<”Function of Class
B2”;
}
};
class C: public B1,
public B2
{
public:
void fun_c()
{
cout<<”Function of Class A”;
}
};
void main()
{
C O1;
O1.fun_c(); //valid
O1.fun_b1(); //valid as publicly inherited
from base B1
O1.fun_b2(); // valid as publicly inherited
from base B2
O1.fun_a();
// valid as only one copy of function in //class C
}
l The
keyword virtual and visibility mode can appear in either order.
l Now
Class A becomes virtually base class of class C
No comments:
Post a Comment