Showing posts with label Virtual Functions. Show all posts
Showing posts with label Virtual Functions. Show all posts

Practical Example of Using Virtual Functions II

From the past few articles we have been discussing about Virtual
Functions.
Before taking up another topic for discussion I thought
of providing one more example of how and when virtual functions may be used.
So, here it is, a practical
example of virtual function.


As virtual functions and Run-Time
Polymorphism
goes hand-in-hand so the example here may also serve as
an example of the use of run-time polymorphism.



// Example to illustrate
// the use of virtual functions
// and run-time polymorphism
#include <iostream.h>

// -- SORT CLASS --
class sort
{
protected:
int *arr;
int num_elmnt;

public:
sort(int);
~sort();
void get_elmnt();
void show_elmnt();
virtual void do_sorting()=0;
};

// takes an argument
// which is the number of
// elements we want
sort::sort(int x)
{
num_elmnt=x;
arr=new int[num_elmnt];
}

sort::~sort()
{
// free up he allocated memory
delete []arr;
}

void sort::get_elmnt()
{
// input elements
cout<<"\nEnter Elements...";
for(int i=0;i<num_elmnt;i++)
{
cout<<"\n#"<<i+1<<":";
cin>>arr[i];
}
}

void sort::show_elmnt()
{
// display the elements
cout<<"\nElements are...";
for(int i=0;i<num_elmnt;i++)
{
cout<<"\n#"<<i+1<<":";
cout<<arr[i];
}
}
// -- SORT CLASS ENDS --

// -- BUBBLE SORT CLASS --
class bubble_sort : public sort
{
public:
// constructor only calls the
// base constructor with the
// parameter
bubble_sort(int x):sort(x){}

void do_sorting();
};

void bubble_sort::do_sorting()
{
int temp;

// do bubble sorting
for(int i=0;i<num_elmnt;i++)
for(int j=0; j<(num_elmnt-1); j++)
if (arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
// -- BUBBLE SORT CLASS ENDS --

// -- SELECTION SORT CLASS --
class selctn_sort : public sort
{
public:
// just call the base class
// constructor
selctn_sort(int x):sort(x){}
void do_sorting();
};

void selctn_sort::do_sorting()
{
int temp;

// do selection sorting
for(int i=0;i<(num_elmnt-1);i++)
for(int j=i+1;j<num_elmnt;j++)
{
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
};
// -- SELECTION SORT CLASS ENDS --

void main()
{
bubble_sort bubble(3);
selctn_sort selctn(5);
sort *ptr;

ptr=&bubble;
ptr->get_elmnt();
ptr->do_sorting();

ptr=&selctn;
ptr->get_elmnt();
ptr->do_sorting();

// again point to bubble
ptr=&bubble;
ptr->show_elmnt();

// again point to selctn
ptr=&selctn;
ptr->show_elmnt();
}


Related Articles:


Properties of Pure Virtual Functions

In the article Properties
of Virtual Functions
, we discussed about two properties of virtual
functions in detail. In this article we’ll be discussing about some properties
of Pure
Virtual Functions.


Property #1: We know that a
base class can’t define a pure virtual function and at the same time its
derived class must define it. But what if the derived class is used as base
for deriving yet another class; is this possible?


Yes, it is, as is obvious from the following program:



#include <iostream.h>

// base class
class base
{
public:
// pure virtual function
// declaration
virtual void func() = 0;
};

// derived class
class derived1 : public base
{
public:
// must define
void func()
{
cout<<"Derived1's func()\n";
}
};

// derived from class derived1
class derived2 : public derived1
{
public:
void func()
{
cout<<"Derived2's func()\n";
}
};

// main
void main()
{
derived1 d1;
derived2 d2;

d1.func();
d2.func();
}


Hence strictly speaking, a pure virtual function cannot be declared and defined
in the same class.


Property #2: While it’s
necessary for a derived class to override a pure virtual function but if we
derive yet another class from that derived class then it’s not necessary
for the newly derived class to override that function.


So that means, if we have a hierarchy of derived classes then a pure virtual
function must be overridden at least once.


It is clear from the following program:



#include <iostream.h>

// base class
class base
{
public:
// pure virtual function
// declaration
virtual void func() = 0;
};

// derived class
class derived1 : public base
{
public:
// must define
void func()
{
cout<<"Derived1's func()\n";
}
};

// derived from class derived1
class derived2 : public derived1
{
public:
// may not override the
// pure virtual function
};

// main
void main()
{
derived1 d1;
derived2 d2;

d1.func();

// derived1's function will
// be called
d2.func();
}


Property #3: We know that we
can’t declare objects of Abstract
Classes
but since C++ offers very powerful Polymorphism
capability, we can have their pointer (as well as references).


It is clear from the following program:



#include <iostream.h>

// base class
class base
{
public:
// pure virtual function
// declaration
virtual void func() = 0;
};

// derived class
class derived1 : public base
{
public:
// must define
void func()
{
cout<<"Derived1's func()\n";
}
};

// derived from class derived1
class derived2 : public derived1
{
public:
void func()
{
cout<<"Derived2's func()\n";
}
};

// main
void main()
{
// although objects of abstract classes
// cannot be declared but we can have
// their pointers
base *bptr;

derived1 d1;
derived2 d2;

// point to derived1 's object
bptr=&d1;

// derived1's func will be called
bptr->func();

// point to derived2's object
bptr=&d2;

// derived2's func will be called
// same interface is used
// but different function
// is called
bptr->func();
}


Related Articles:


Practical Example of Using Virtual Functions

From the past few articles we have been discussing about virtual functions
but we are yet to observe any of its practical use, this article would do that!


In this article we are going to show you a very simple program that illustrates
the practical use of virtual functions.


Please read the code carefully!



// Practical example of
// when virtual functions are
// used
#include <iostream.h>

class area
{
protected:
int mag;
double a;

public:
area(int x){mag=x;}
double get_area(){return a;}

// pure virtual function
virtual void compute()=0;
// it is made pure as
// it couldn't have any meaningful
// definition since area can only
// be defined w.r.t something specific
};

class circle_area : public area
{
public:
circle_area(int x) : area(x){}

// now that we are referring
// to area w.r.t a circle so
// it is natural that we define
// it
void compute()
{
a=(mag*mag)*3.14;
}
};

class square_area : public area
{
public:
square_area(int x) : area(x){}

// same for this!
void compute()
{
a=mag*mag;
}
};

void main()
{
square_area sa(10);
circle_area ca(20);

sa.compute();
ca.compute();

cout<<"Area of square: "<<sa.get_area();
cout<<endl;
cout<<"Area of cirlce: "<<ca.get_area();
}


Related Articles:


Pure Virtual Functions

From the previous article Properties
of Virtual Functions
, we know that a virtual function may or may not
be overridden in the derived lasses. It means, it is not necessary for a derived
class to override a virtual function.


But there are times when a base class is not able to define anything meaningful
for the virtual function in that case every derived class must provide its own
definition of the that function. To force this type of overriding you use the
following general form to declare a virtual function:



virtual ret-type func-name(arg-list)=0;


This type of virtual function is known as Pure Virtual Function.


There are two major differences between a virtual and a pure virtual function,
these are below:




  • There CAN’T be a definition of the pure virtual function in the base
    class.




  • There MUST be a definition of the pure virtual function in the derived
    class.




By making a virtual function ‘Pure’, it becomes necessary for the
derived classes to override it, further since the base class can’t define
a pure virtual function, we can’t have objects of that class. These types
of incomplete classes (having one or more pure virtual function) are known as
Abstract Classes and are used extensively.


The following program illustrates this:



// Pure Virtual Functions
#include <iostream.h>

// base class
class base
{
public:
// pure virtaul function
// declaration
virtual void func() = 0;
// can't define
};

// derived class
class derived : public base
{
public:
// must define
void func()
{
cout<<"Derived1's func()\n";
}
};

// main
void main()
{
// --CODE: base b
// won't work because we
// can't have objects of
// absract classes
derived d1;

d1.func();
}


Related Articles:


Properties of Virtual Functions

From the previous two articles Introduction
to Virtual Functions
and Virtual
Functions and Run-time Polymorphism
, we have been discussing about
Virtual Functions.


In this article we’ll be discussing about two important properties of
Virtual Functions.


As properties can be better understood by examples, we’ll be using them
more rather than text and definitions that could confuse you.


Property #1:



// Properties of virtual functions
#include <iostream.h>

// base class
class base
{
public:
virtual void func()
{
cout<<"Base's func()\n";
}
};

// derived class
class derived1:public base
{
public:
// this is a virtual function
void func()
{
cout<<"Derived1's func()\n";
}
};

// derived from another
// derived class
class derived2:public derived1
{
public:
// still virtual
void func()
{
cout<<"Derived2's func()\n";
}
};

// main
void main()
{
base b;
derived1 d1;
derived2 d2;

b.func();
d1.func();
d2.func();
}


OUTPUT:

Base's func()
Derived1's func()
Derived2's func()

The code above illustrates that when a class is derived from another derived
class (which has inherited a virtual function from its base class) then also
the virtual function can be overridden. So, it means that once declared virtual,
a function (no matter how many times inherited in hierarchy) still remains Virtual
and hence can be overridden.


Property #2: This is an extension
of the previous property, as you know that a virtual function remains virtual
no matter how many times it is inherited in a hierarchy, but what if one of
the derived class doesn’t overrides it, what will happen then? The following
code answers this!



// Properties of virtual functions
#include <iostream.h>

// base class
class base
{
public:
virtual void func()
{
cout<<"Base's func()\n";
}
};

// derived class
class derived1:public base
{
public:
// this is a virtual function
void func()
{
cout<<"Derived1's func()\n";
}
};

// derived from another
// derived class
class derived2:public derived1
{
public:
// no overriding
};

// another derived class
class derived3:public derived2
{
public:
// can still be overridden
void func()
{
cout<<"Derived3's func()\n";
}
};

// main
void main()
{
base b;
derived1 d1;
derived2 d2;
derived3 d3;

b.func();
d1.func();

// will call the function overridden
// by its base class because it didn't
// override the function
d2.func();

d3.func();
}


OUTPUT:

Base's func()
Derived1's func()
Derived1's func()
Derived3's func()

The above code is pretty much self-explanatory so I don’t think it needs
further explanations.


Related Articles:


Virtual Functions and Run-time Polymorphism

Before beginning this I would like to tell you one thing through the following
program:



// Virtual Functions and
// Run-time Polymorphism
#include <iostream.h>

// base class
class base
{
public:
int a;
};

// derived class
class derived:public base
{
public:
int b;
};

// main
void main()
{
base b;
derived d;

// base class pointer
base *bptr;

// pointer pointing
// to base's object
bptr=&b;

bptr->a=10;

// pointer pointing
// to derived's object
bptr=&d;

// still is able to access
// the members of the base
// class
bptr->a=100;
}


The property above combined with virtual function can be used to achieve a
very special and powerful feature, known as run-time polymorphism.


We had discussed about What
is Polymorphism
before so we wont be discussing it here.


The program below illustrates how virtual functions can be used to achieve
run-time polymorphism.


Please read the code carefully so that you understand how it’s working.



// Using Virtual functions to
// achieve run-time Polymorphism
#include <iostream.h>

// base class
class base
{
public:
virtual void func()
{
cout<<"Base's func()\n";
}
};

// derived class
class derived:public base
{
public:
void func()
{
cout<<"Derived's func()\n";
}
};

// main
void main()
{
int ch=0;

base b;
derived d;

// base class pointer
base *bptr;

while(ch!=3)
{
cout<<"1> Call Base's func\n";
cout<<"2> Call Derived's func\n";
cout<<"3> Quit\n";

cin>>ch;

switch(ch)
{
case 1:
// point to base's object
bptr=&b;
break;

case 2:
// point tp derived's object
bptr=&d;
break;

default:
bptr=&b;
}

// call whichever function
// user has chosen to call
bptr->func();
}
}


Related Articles:


Introduction to Virtual Functions

Virtual functions are special member functions of a class which may be re-defined
in the derived classes. It is used to give specific meaning to the base class
member function with respect to the derive class.


Virtual functions can be thought of as a function name reserved in the bas
class which may be re-defined in the derived classes as per the need so that
every derived class has the same function that performs specific (as redefined
in the derived class) action.


Let’s now have a look at a simple program to show virtual functions inaction:



// Virtual functions
#include <iostream.h>

// base class
class base
{
public:
// precede the function name
// with the 'virtual' keyword
// to make it a virtual function
virtual void func()
{
cout<<"Base's func()\n";
}
};

// derived class
class derived:public base
{
public:
// redefinition of the
// function
void func()
{
cout<<"Derived's func()\n";
}
};

// main
void main()
{
base b;
derived d;

// notice that both are calling
// the same function but different
// functions gets called as per
// the class to which the object
// belongs to
b.func();
d.func();
}


OUTPUT:


  Base's func()
Derived's func()


The redefinition of the virtual function in the derived class is known
as overriding





As you can see there is nothing confusing, the virtual function is a general
member function and is defined as such, only difference being that it’s
preceded by the virtual keyword that gives it the special property.


NOTE: By redefining a virtual function, all its previous meaning (as was defined
in the base class) is lost.


As in the example program the base class defines the virtual function to print
“Base's func()” and the derived class overrides it to print “Derived's
func()”. So when we call the overridden function it only prints what was
defined in the redefinition hence the original meaning of the function is lost.


Related Articles:


Check out this stream