Showing posts with label Polymorphism. Show all posts
Showing posts with label Polymorphism. 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:


What is Polymorphism?

Polymorphism means to have one interface for different methods or functions.
It is the ability through which we can do different operations (by calling different
functions) from the same interface.


In C++ functions and operators can be made to be polymorphic, but in this article
we’ll only be discussing about polymorphic functions.


There can be two types of polymorphism which are discussed below:


Compile-Time Polymorphism: When we have two or more polymorphic function (overloaded
functions) and the call to a particular function is resolved (or known) at the
compile-time, it is called compile-time polymorphism.


The following example program illustrates this. Please read the comments for
further information.


   // program to demonstrate
// compile-time polymorphism
#include<iostream.h>

// -- FUNCTION PROTOTYPES --
// -- OVERLOADED FUNCTIONS --
void func(int);
void func(char *);
// -- ENDS --


void main()
{
// by seeing the argument

// passed, anyone can tell
// which version of the
// function is being called
// hence call to particular
// polymorphic functions is
// resolved or known at the
// time of compilation
func(10);
func("Polymorphism");
}

void func(int a)
{
cout<<a;
cout<<endl;
}

void func(char *str)
{
cout<<str;
cout<<endl;
}


Run-Time Polymorphism: When the call to a particular function (out of the many
polymorphic functions) is not resolved (or known) until execution then it is
called run-time polymorphism.


The following example program illustrates this. Pay extra attention to the
comments!



// Program to demonstrate
// run-time polymorphism
#include<iostream.h>

// -- FUNCTION PROTOTYPES --
void func1();
void func2();
// -- ENDS --

void main()
{
int ch=0;
// here pointer to function
// is declared which will
// be used to call one of
// the two functions
void (*ptr)();

while(ch!=3)
{
cout<<"1> Call Func1";
cout<<"\n2> Call Func2";
cout<<"\n3> Quit\n";

cin>>ch;

switch(ch)
{
case 1:
// make 'ptr' point
// to func1
ptr=func1;
break;

case 2:
// make 'ptr' point
// to func2
ptr=func2;
break;
}

// call whichever
// function is selected
// PLEASE NOTE THAT IT IS
// NOT POSSIBLE TO TELL
// WHICH OF THE TWO
// FUNCTION WILL BE
// CALLED. HENCE CALL
// TO A PARTICULAR
// PLOYMORPHIC FUNCTION
// REMAINS UNRESOLVED
(*ptr)();
}
}

// -- FUNCTIONS DEFINITION --
void func1()
{
cout<<"Called Func1!\n";
}

void func2()
{
cout<<"Called Func2!\n";
}
// -- ENDS --



Good-Bye!


Related Articles:


A Multi-Purpose String Class in C++

NOTE: Here I present you with a String Class in C++. We have
pre-defined string class (CString in Microsoft Visual C++) which has similar but
more powerful to the one presented here but using something is one thing and learning
how it works is another. Here I show you how string functions actually work. All
the functions are programmed from the scratch without using any other standard
library function. Look at the program (Class) carefully and try to understand
how each of the function is working.

  //-----------------------------
//-----------myClass-----------
//----A String Class in C++----

#include<iostream.h>
#include<stdlib.h>

class myString
{
private:

// these functions are not
// needed outside the class
void allocate(int);
void copy(char *, char *);

public:

   char *string;

// member functions
myString();
myString(char *);
int getLength();
int getLength(char *);
void empty();
bool isEmpty();
void putString(char *);
char *getString();
char *fromLeft(int);
char *fromRight(int);
char *fromMid(int, int);
~myString();
};

//--------------------------------
//------------MEMBER--------------
//---FUNCTION DEFINITION STARTS---
void myString::allocate(int size)
{
empty();

string=new char[size];
if(string==NULL) exit(0);
}

void myString::copy(char *str1, char *str2)
{
int length=getLength(str2);

for(int i=0;i<=length;i++)
str1[i]=str2[i];
}

void myString::empty()
{
if(string!=NULL)
{
delete []string;
string=NULL;
}
}

bool myString::isEmpty()
{
if(string!=NULL)
return false;

return true;
}

int myString::getLength(char *str)
{
int i=0;

while(str[i]!='\0')
i++;

return i;
}

int myString::getLength()
{
if(string!=NULL)
return getLength(string);

return -1;
}

myString::myString(char *str)
{
string=NULL;
int size=getLength(str)+1;

allocate(size);

copy(string,str);
}

myString::myString()
{
string=NULL;
}

void myString::putString(char *str)
{
int size=getLength(str)+1;

allocate(size);

copy(string,str);
}

char *myString::getString()
{
if(string!=NULL)
{
return string;
}
}

myString::~myString()
{
if(string!=NULL)
delete []string;
}

char *myString::fromLeft(int chr)
{
if(string!=NULL)
{
char *temp;
temp=new char[chr+2];

if(temp==NULL) exit(1);

for(int i=0;i<chr;i++)
temp[i]=string[i];

temp[i]='\0';
return temp;
}
}

char *myString::fromRight(int chr)
{
if(string!=NULL)
{
char *temp;
temp=new char[chr+2];
int a=0;

if(temp==NULL) exit(1);

int i=getLength()-1;
int j=(i-chr)+1;

for(j;j<=i;j++)
{
temp[a]=string[j];
a++;
}
temp[a]='\0';
return temp;
}
}

char *myString::fromMid(int a,int b)
{
if(string!=NULL)
{
int size=b+1;
char *temp;
temp=new char[size];
int i=a,j=0,k=(a+b);

for(i;i<k;i++)
{
temp[j]=string[i];
j++;
}
temp[j]='\0';
return temp;
}
}
//-----------MEMBER-------------
//---FUNCTION DEFINITION ENDS---
//------------------------------

void main(void)
{
myString a("Learning C++ Programming");

cout<<a.getString();
cout<<endl;
cout<<a.fromLeft(3);
cout<<endl;
cout<<a.fromRight(3);
cout<<endl;
cout<<a.fromMid(3,3);
cout<<endl<<a.isEmpty();

a.empty();
// will not print anything
cout<<endl<<a.fromLeft(3);
// will print true(0)
cout<<endl<<a.isEmpty();
}


Good-Bye for now!


Check back for updates...

Introduction to Function Overloading in C++

Let us start this with a question!


All of you know that we cannot have two variables of the same name, but can
we have two Functions having the same name.


The answer is YES, we can have two functions of the same name by a method known
as function overloading and the functions having the same name are known as
overloaded functions.


So, what’s the use of Function Overloading


Function overloading is one of the most powerful features of C++ programming
language. It forms the basis of polymorphism (compile-time polymorphism).


Most of the time you’ll be overloading the constructor function of a
class.


How function overloading is achieved


One thing that might be coming to your mind is, how will the compiler know
when to call which function, if there are more than one function of the same
name.


The answer is, you have to declare functions in such a way that they differ
either in terms of the number of parameters or in terms of the type of parameters
they take.


What that means is, nothing special needs to be done, you just need to declare
two or more functions having the same name but either having different number
of parameters or having parameters of different types.


Example 1: Overloading Functions that differ in terms of NUMBER
OF PARAMETERS


  //Example Program in C++
#include<iostream.h>

//FUNTION PROTOTYPES
int func(int i);
int func(int i, int j);

void main(void)
{
cout<<func(10);//func(int i)is called

cout<<func(10,10);//func(int i, int j) is called
}

int func(int i)
{
return i;
}

int func(int i, int j)
{
return i+j;
}

Example 2: Overloading Functions that differ in terms of TYPE
OF PARAMETERS


  //Example Program in C++
#include<iostream.h>

//FUNTION PROTOTYPES
int func(int i);
double func(double i);

void main(void)
{
cout<<func(10);//func(int i)is called

cout<<func(10.201);//func(double i) is called
}

int func(int i)
{
return i;
}

double func(double i)
{
return i;
}

One more Question, is the program below, valid?


  //Example Program in C++
#include<iostream.h>

//FUNTION PROTOTYPES
int func(int i);
double func(int i);

void main(void)
{
cout<<func(10);

cout<<func(10.201);
}

int func(int i)
{
return i;
}

double func(int i)
{
return i;
}

No, because you can’t overload functions if they differ only in terms
of the data type they return.


I Hope this article throws some light on function overloading!


Good-Bye for now


Thanks for reading…


Do check back for updates!


Related Articles:


Check out this stream