5 Inheritance



Reusability:  
Means reusing code written earlier, may be from some previous project or from the library.  Reusing old code not only saves development time, but also saves the testing and debugging time.  It is better to use existing code which has been time-tested rather than reinvent it.  Moreover, writing new code may introduce bugs in the program.  Code, written and tested earlier, may relieve a programmer from details and so on.  It leaves the programmer more time to concentrate on overall logistics of the program.

Inheritance:
Inheritance means deriving new classes from the old ones.  The old class called as base class and the class derived from the base class is called as derived class.  base class is also called as parent class and derived class as child class.  Deriving a new class from an existing one, allows redefining a member function of the base class and also adding new members to derived class.  this is possible without having source code of class definition.  All that is required is class library, which does not require any recompilation.  The base class remains unchanged in the process.

Protected access specifier:
The protected section is exactly like the private section in terms of scope and access i.e. like private members, protected members also can be accessed only by the members of that class.  But difference between them is that the private members of a class cannot be derived, only protected members of base class can be derived.  In other words, members of the derived class can access protected members only; they cannot access private members of the base class.  This is what called as information hiding.  Hence if a class is designed to be used in any future project, then members which may be used in the derived class should be made protected and not private.

Deriving an example:
Example 1 (Boxclass.cpp)
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
class boxclass{
protected:
int x1,x2,y1,y2;
public:
boxclass(int ax1,int ay1,int ax2,int ay2){
x1=ax1;
y1=ay1;
x2=ax2;
y2=ay2;
}


void boxdraw(void){
int x;
gotoxy(y1,x1);
putch(201);
gotoxy(y1+1,x1);
x=y2-y1;
while(--x)
putch(205);
putch(185);
for(x=x+1;x<=x2;++x){
gotoxy(y1,x);
putch(186);
gotoxy(y2,x);
putch(186);
}
gotoxy(y1,x2);
putch(200);
gotoxy(y1+1,x2);
x=y2-y1;
while(--x)
putch(205);
gotoxy(y2,x2);
putch(188);
}
};
Extending the class:  
If another application requires this class with further extensions then a new class can be derived from boxclass.

Example 2(box2.cpp)
#include “box1.cpp”
class newbox:public boxclass
{
protected : int attrib;
public:
newbox (int ax1, int ay1, int ax2, int ay2, int attr):boxclass(ax1, ay1, ax2,  ay2)

{
atrrib = atrr;
};
void boxdraw(void)
{
struct text-infor s;
gettextintfor(&s);                                // old atrrib
text attr(attrib);                                   // set new attrib
boxclass :: boxdraw( );                        // draw a box
text attr(s.attribute);                            // set old attrib back
boxclear( );

};
struct text-infor s;
get text infor(&s);
window(y1+1, x1+1, y2-1, x2-1);
text attrib(attrib);
clrscr( );
textattr(s.attribute);                             // reset old setting
window(s.winleft, s.wintop, s.winright, s. winbottom);
};
};
int main(void){
boxclass  b1(5,5,20,75);
boxclass  b2(10,25,15,55);
clrscr( );
b1.boxdraw( );
b2.boxdraw( );
}

The name of the derived class comes before the colon and name of base class follows the colon preceded by the keyword public – this is the access specifier for entire derived class.

Hence public members of the base class become public members of derived class and protected members become protected members.  Private members are inaccessible in derived class.  this access specifier can also be private in which case, objects of derived class cannot access any member functions of derived class can access protected and public members of the base class.  The default for this access specifier is private.  The derived class which has been publicly inherited can be further inherited by another derived class.

The, declaring an object of derived class declares an object of base class.  declaration of the derived class calls constructor for it which in turn should make a call to base class constructor using single colon.  Derived class constructor is responsible for initializing the additional data members from derived class, where as base class constructor is responsible for initializing inherited members of the base class.  Program first calls the base bass class constructor and then derived class constructor.

Using Derived Class:
Example 3
#include<conio.h>
#include<iostream.h>
#include "e:\sandhya\c\BoxClass.cpp"
void main (void){
clrscr( );
boxclass b1(20,20,50,80);       // blink attrib
boxclass b2(22,22,45,45);       // highlight attrib
boxclass b (30,30,35,35);
b1.boxdraw( );                                    // derived class object
b2.boxdraw( );                                    // derived class object
b.boxdraw( );                                      // base class object
getch( );
}



More on class Inheritance
Class inheritance has given a new dimension to the idea of reusability of code.  We can also derive multiple classes from a single base class.

Nested classes:
Many times it becomes necessary to have a class contain properties of two other classes.  One way is to define a class within another- that is a class with member class also called as nested classes.  For example,

class Aclass
{
private:
            int privatevar;
public:
            Aclass(int pv)
{
privatevar = pv;
};
void publicfn( )
{
……
};
};
class Bclass
{
private:
int Privvar;
Aclass Aobj;                            // Declaring a object
public:
Bclass(int bpv, int apv):Aobj(apv)
{
Privvar = bpv;
};
void publicfn( ){
…………
};
};

The part after the colon in the definition of a constructor is called as initialization section and actual body of the constructor function is called as assignment section.  Initialization section initializes base class members, and assignment section contains statements to initialize the derived class members.  In case of initialization section derived classes name of the base class constructor is written after the colon.  This base class constructor is called before the constructor in derived class.  The members in initialization section must be separated by commas.

Multiple inheritance:  
Multiple inheritance is the deriving a class from more than one class.

Example 1
class A {
public:void print( ){
printf(“\n High hellos”);
};
};
class B{
public:
void print( ){
printf(“High Hello, Goa Challo”);
};
};
class C: public A, Public B                 // multiple inheritance
{
public:
void print( )
{
printf(“Training A & B”);
};
void main(void)
{
A objA;
B objB;
C objC;
objC.A::print( );
obj.B::print( );                         // from class A
objC.print( );                           // from class B
}

Multiple inheritance with a common base:
In C++ it is possible to inherit a class from two different classes which in turn have been derived from the same base class.

Example 2
class base{
void print( ){
printf(“\n I am the Base Class”);
};
class Aclass: public base{
void print( ){
printf(“\n I am Class A”);
};
class Bclass: public base{
void print( ){
printf(“\n I am From Class B”);
};

class derived: public Aclass, public Bclass{
printf(“\n I am derived from A and B Class”);
};
void main (void){
base bt,
Aclass A;
Bclass B;
Derived D;
Base bt.print( )
}

Virtual Base Classes:  
In the above program Aclass and Bclass are two classes derived from same base class.  derived class is derived from these two class.  the problem in the above program is that both Aclass and Bclass are derived from base and hence both of them contains a copy of a base class members.  Now when derive is derived from them, it contains a copy of the data members of both the classes.  Which means it contains two copies of base class members one from Aclass and other from Bclass which gives rise to ambiguity between base data members.  Another problem is that declaring an object of derive class will invoke base class constructor twice.  Solution to this problem is provided by virtual base class.

This can be done by making the base class a virtual base class.  this keyword makes the two classes share a single copy of their base class.  The format is:
Class base
{
………
……….
};
class Aclass:virtual public base
{
……….
};
class Bclass:virtual public base
{
-…………
};
class derived: public Aclass, public Bclass
{
………
………
};

Abstract Classes:
This class is a general class whose sole purpose is to serve as a base class for the other three.  Classes used only for the purpose of deriving other classes from them are called as abstract classes.  Abstract classes are not used to define an object(instance) of these classes, they are simply there to serve as base class.  e.g.

Class Base
{

………};
class A:public base
{
…………};
class B: public base
{
…………};
class C: public base
{
……....};
void main(void)
{
A obj A;
B obj B;
C obj C;
……..…
………..
………..
}

Pointers to Objects:
Pointers can be made to point to objects as well.  The usage of pointer with classes is exactly same as in structures.  And like structures the structure pointer à can be used to access members of the class.   For Example

void main(void)
{
person Jazz;                                                     //object
Jazz.getname( );
Jazz.putname( );
person *boss;                                                   // pointer to object
boss = new person;                                          //allcate memory
bossÚgetname( );
bossÚputname( );
delete boss;
}

A constructor, if defined, is invoked when an object pointer is allocated memory through new.  Similarly destructor is invoked when memory allocated to an object pointer is released through delete.  Pointers to objects can be used to form complex data structures with inheritance pointers can be come problematic.

Example 3
# include<stdio.h>
class shape
{
public:
void print(void)
{
printf(“ I am a Shape”);

};
};
class Triangle: public shape
{
public:
void print(void)
{
printf(“I am a Triangle\n”);
};
};
class Circle
{
public:
void print(void)
{
printf(“I am a Circular Shaple\n”);
};
};
void main (void)
{
shape shapeA;
Triangle TriangleA;
Circle Circ;
ShapeA.print( );
TriangleA.print( );
Circ.print( );
Printf(“\n\n”);
Shape *ptr;
ptr = &shapeA;
ptrÚprint( );
ptr = &TriangleA;
ptrÚprint( );
ptr= &Circ;
ptrÚprint( );
}
In the above example the first part works fine.  But for second part for each of the calls with different addresses, the function from base class shape is executed and compiler ignores the contents of the pointer.

Virtual Functions:
The above problem can be shoveled with the virtual functions.  The function of the base class can be declared with the keyword virtual.

Example 4
#include<stdio.h>
class Father
{
public:
virtual void print(void)
{
printf(“I am the Father\n”);
};
};
class Son: public Father
{
void print(void)
{
printf(“I am A Son\n”);
};
};
class GrandSon: public Father
{
void print(void)
{
printf(“I am The Grandson\n”);
};
};
void main (void)
{
Father Abc;
Son Xyz;
GrandSon Lky;
Abc.print( );
Xyz.print( );
Lky.print( );
Printf(“\n\n”);
Father *ptr;
Ptr = &Abc;
PtrÚprint( );
Ptr = &Xyz;
PtrÚprint( );
Ptr =&Lky;
PtrÚprint( );
}

From the above program the compiler selects the function to be invoked, based upon the contents of the pointer and not the type of the pointer.  This facility is very effective when many classes are derived from one base class.  Member functions of each of these can be then invoked using a pointer to base class.

Pure Virtual Functions:
An abstract class is one which is used just for deriving some other classes.  No object of this class is declared and used in the program.  Similarly there are pure virtual functions. 

Example 5
#include<stdio.h>
class shape
{
public:
virtual void print(void)=0                   // pure virtual funtion
{
print(“I am A Shape”);
};
};
class Triangle: public shape
public:
{
void print(void)
{
print(“I am Three Sided Shape”);
};
};
class Circ:public shape
{
public:
void print(vid)
{printf(“I Do not have a Sides”);
};
};
class Rect:public shape
{
public:
void print(void)
{
printf(“ I have four sides”);
};
};
int main(void){
Triangle trin;
Circ Circle;
Rect Rect1;
Shape *ptr;
ptr = &Trin;
ptrÚprint( );
ptr = &Circle;
ptrÚprint( );
ptr = &Rect1;
ptr Úprint( );
}

Dynamic Binding:
Compiler transfers the functions in the program, if it does not contain any errors.  But functions themselves are kept distinct in the object code file.  Calls made to functions are not resolved instead an entry is made into reference table.  Linker resolves these references by fetching the appropriate functions from the object code of the program or from the library.  This is called as Static or early binding.  Object code of functions to which calls are not made in the program are not linked in the final executable program.

The appropriate functions are called only at runtime this is called as dynamic  binding or late binding.

Static Class Members:
An object is  nothing but an instance of a class.  class can have many objects.  All objects have different data members but invoke the same member functions with one exception.  If a data member is declared with the keyword static, then only one such data item is created for the entire class.  static data members are useful if all objects of a class must share a common data item remains same duration of this variable is for the entire lifetime of the program.  Static variable is useful if an object requires to know how many of its kind are existing. 

Example 6
#include<stdio.h>
class counter
{
private:
static int count;
public:
counter(void)
{
count++;
};
int getcount(void)
{
return (count);
};
};
int counter :: count =0;                        // initialization of static member.
void main(void)
{
counter c1, c2;
printf(“Count = %d\n”,c1.getcount( ));
printf(“Count = %d\n”,c2.getcount( ));
counter c3,c4,c5;
printf(“Count = %d\n”,c3.getcount( ));
printf(“Count = %d\n”,c4.getcount( ));
printf(“Count = %d\n”,c5.getcount( ));
}

Static function Members:
Static data members of a class are shared by all the objects of that class.  but in above example’s output the number of objects remains same at a given  instance.  In fact use of existing objects is not an efficient way to access the value of static data member.  Specific object should not be used to refer to this member, since it does not belong to that object, it belongs to the entire class.  hence static function members have to be defined. I.e. to invoke such a function, an object name is not required. 

Example 7
#include<stdio.h>
class counter
{
private:
static int count;
public:
counter(Void)
{
count++;
};
static int getcount(void)
{
return(count);
};
};
int counter::count=0;
void main(void)
{
counter c1,c2;
printf(“Total = %d\n”,counter:getcount( ));
counter c3,c4,c5;
printf(“Total = %d\n”,counter:getcount( ));
}


Practical Session 5
Example 1
#include<iostream.h>
#include<conio.h>
#include<string.h>
class Father{
char name[20];
public:
Father(char *fname)
{
strcpy(name,fname);
}
virtual void show( ){
cout<<"\n Father Name : "<<name;
}
};
class Son:public Father
{
char name[20];
public:
Son( char *sname,char *fname):Father (fname)
{
strcpy(name,sname);
}
void show( ){
cout<<"\n Sons Name : "<<name;
}
};
void main( ){
clrscr( );
Father *fp;
Father f1("Vinod");
fp=&f1;
fp->show( );
Son s1("Devender","Vinod");
fp->show( );
s1.show( );
getch( );
}
Example 2
#include<iostream.h>
#include<conio.h>
const float pi=3.142;
class radian
{
float rad;
public:
radian( ){
rad=0.0;
}
 radian(float initrad)
{
rad=initrad;
}
float getradian( )
{
return(rad);
}
void input( ){
cout<<"\n Enter Radian :";
cin>>rad;
}
void output( ){
cout<<"\n Radian  "<<getradian( );
}
};
class degree{
float degree;
public:
degree( ){
degree =0.0;
}
degree(radian rad)
{
degree=rad.getradian( )*180.0/pi;
}
float getdegree( )
{
return(degree);
}
operator radian( )
{
return(radian(degree *pi/180.0));
}
void input( )
{
cout<<"\n Enter Degree  :";
cin>>degree;
}
void output( ){
cout<<"\n Degree  : "<<degree;
}
};
void main( )
{
clrscr( );
degree d1,d2;
radian r1,r2;
d1.input( );
r1=d1;
r1.output( );
r2.input( );
d2=r2;
d2.output( );
getch( );
}



Example 3(Multiple Inheritance)
#include<iostream.h>
#include<conio.h>
class A
{
char ch;
public:
A(char c)
{
ch=c;
}
void show( )
{
cout<<ch;
}
};
class B
{
char ch;
public:
B(char b)
{
ch=b;
}
void show( )
{
cout<<ch;
}
};
class C:public A,public B
{
char ch;
public:
C(char c1,char c2,char c3):A(c1),B(c2)
{
ch=c3;
}
void show( ){
A::show( );
B::show( );
cout<<ch;
}
};
void main( ){
clrscr( );
C ob('a','b','c');
cout<<"\n object ";
ob.show( );

cout<<"\n object C ";
ob.C::show( );
cout<<"\n object A ";
ob.A::show( );
cout<<"\n object B ";
ob.B::show( );
getch( );
}
Example 4(Pointer To an Object)
#include <stdio.h>
class person{
private:
char name [60];
public:
void getname(void){
printf(“\n Enter Name:”);
gets(name);
};
void putname(void){
printf(“Name is % s\n”,name);
};
};
void main(void){
person Jazz;                                                     //object
Jazz.getname( );
Jazz.putname( );
person *boss;                                                   // pointer to object
boss = new person;                                          //allcate memory
bossÚgetname( );
bossÚputname( );
delete boss;
}
Example 5
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<string.h>
class player{
protected:
int age,runs;
char name[20],state[20];
public:
void getstats(void);
void showstats(void);
};
void player::getstats(void){
printf("\n Enter Player name  ");
scanf("%s",&name);
printf("\n Enter Players Age  ");

scanf("%d",&age);
printf("\n Enter State  ");
scanf("%s",&state);
}
void player::showstats(void){
printf("\n Player Name  %s",name);
printf("\n Players Age %d",age);
printf("\n Player's State %s",state);
}
class oneday:public player{
protected:
int matches,balls,runs,avrg,cent,fifty;
public:
void getdata(void);
void dispdata(void);
};
void oneday::getdata(void){
printf("\n Enter Onedays of the player  ");
scanf("%d",&matches);
printf("\n Enter his Runs  ");
scanf("%d",&runs);
printf("\n Enter Total Balls Played by the player  ");
scanf("%d",&balls);
printf("\n Enter Total Centuries of the player  ");
scanf("%d",&cent);
printf("\n Enter Total Fifties of the player  ");
scanf("%d",&fifty);
avrg=(runs/matches);
}
void oneday::dispdata(void){
printf("\n The One Days are:  %d",matches);
printf("\n Total Runs are:  %d",runs);
printf("\n Total Balls Played:  %d",balls);
printf("\n Total Centuries Made:  %d",cent);
printf("\n Total Fifties Made:  %d",fifty);
printf("\n The Average is:  %d",avrg);
}
class Test:public player{
protected:
int matches,balls,runs,avrg,cent,fifty;
public:
void getdata1(void);
void dispdata1(void);
};
void Test::getdata1(void){
printf("\n Enter Test Matches of the player  ");
scanf("%d",&matches);
printf("\n Enter his Runs  ");
scanf("%d",&runs);

printf("\n Enter Total Balls Played by the player  ");
scanf("%d",&balls);
printf("\n Enter Total Centuries of the player  ");
scanf("%d",&cent);
printf("\n Enter Total Fifties of the player  ");
scanf("%d",&fifty);
avrg=(runs/matches);
}
void Test::dispdata1(void){
printf("\n The Test Matches are:  %d",matches);
printf("\n Total Runs are:  %d",runs);
printf("\n Total Balls Played:  %d",balls);
printf("\n Total Centuries Made:  %d",cent);
printf("\n Total Fifties Made:  %d",fifty);
printf("\n The Average is:  %d",avrg);
}
void main(void){
char ans;
player a;
oneday o;
Test t;
clrscr( );
printf("\n Enter O for One day and T for Test Match Record:  ");
scanf("%c",&ans);
if(ans=='O'){
a.getstats( );
o.getdata( );
a.showstats( );
o.dispdata( );
}
else if(ans=='T'){
a.getstats( );
t.getdata1( );
a.showstats( );
t.dispdata1( );
}
else
printf("\n Record is Wrong ");
getch( );
}

Top

No comments:

Post a Comment