0% found this document useful (0 votes)
10 views

Functionoverloading ch4

Uploaded by

projectai43
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Functionoverloading ch4

Uploaded by

projectai43
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 53

Polymorphism

Function overloading
• Overloading refers to use the same thing for different purposes.
• We can use the same function name to create functions that perform
a variety of different tasks. This is known as function polymorphism
• We can design a family of functions with one function name but with
different argument lists( no of arguments and type)
• Also known as static polymorphism
• Also known as early binding
Square function
int square(int x) sum(int a, double b)
sum(double a, int b)
{ return x*x; }

double square(double y)
{ return y*y;}

float square(float z)
{ return z*z;}
Use overloaded function

Complier will search for the match function prototype


int main()
{
int x=7;
double y=7.5;
cout<<“square of “<<x<<“ is “
<<square(x)<<endl;
cout<<“Square of “<<y<<“is “
<<square(y)<<endl;
}
Function overloading
• A function call first matches the prototype having the same number and type of arguments. It involves following
steps
1. compiler first tries to find an exact match in which types of actual arguments are the same
2 if exact match is not found the compiler uses the integral promotions to actual arguments such as
Char to int
Float to double
• Integral promotion involves the conversion of integer types narrower than int (which includes bool, char, unsigned
char, signed char, unsigned short, and signed short) to an int (if possible) or an unsigned int (otherwise).
• Floating point promotion involves the conversion of a float to a double.

3. When either of them fails, the compiler use implicit assignment conversion to actual arguments. If the conversion
is possible to have multiple match then compiler will generate an error message
• All the data types of the variables are upgraded to the data type of the variable with largest data type.
• bool -> char -> short int -> int -> unsigned int -> long -> unsigned ->long long -> float -> double -> long double
compiler will generate an error message
e.g. long square(long n) and double square(double x)
Call is square(10)
#include<iostream>
using namespace std;
void test(float s,float t)
{
cout << "Function with float called ";
}
void test(int s, int t)
{
cout << "Function with int called ";
}
int main()
{
float a=3.5,b=5.6;
test(a,b);
return 0;
}
Above program work correctly match with float
In function 'int main()': test(3.5,5.6);
13:13: error: call of overloaded 'test(double, double)' is
ambiguous
Ambiguity
void f(unsigned char c)
{
cout<<c;
}
void f(char c)
{
cout<<c;
}
int main()
{
f(‘c’); no ambiguity
f(86); ambiguity
return 0;
}
Ambiguity
• #include<iostream>
using namespace std;
int f(int a,int b)
{ return a*b;}
int f(int a, int &b)
{
return a*b;}
int main()
{
int x=1,y=2;
cout<<f(x,y); return 0;}
in C++, following function declarations cannot be overloaded.
1) Function declarations that differ only in the return type. For example, the following program fails in compilation.

#include<iostream>
int foo() {
return 10;
}

char foo() {
return 'a';
}

int main()
{
char x = foo();
getchar();
return 0;
}
2) Member function declarations with the same name and the same parameter-type-
list cannot be overloaded if any of them is a static member function declaration. For
example, following program fails in compilation.
#include<iostream>
class Test {
static void fun(int i) {}
void fun(int i) {}
};

int main()
{
Test t;
t.fun();
getchar();
return 0;
}
Parameter declarations that differ only in a pointer * versus an array
[] are equivalent. That is, the array declaration is adjusted to
become a pointer declaration. For example, following two function
declarations are equivalent.

int fun(int *ptr);


int fun(int ptr[]); // redeclaration of fun(int *ptr)
#include<iostream>
using namespace std;

class Test
{
int x;
public:
Test (int i):x(i) { }
void fun() const
{
cout << "fun() const called " << endl;
}
void fun()
{
cout << "fun() called " << endl;
}
};
int main()
{
Test t1 (10);
const Test t2 (20);
t1.fun();
t2.fun();
return 0;
}
Output: The above program compiles and runs fine, and
produces following output.

fun() called
fun() const called
// PROGRAM 1 (Fails in compilation)
#include<iostream>
using namespace std;

void fun(const int i)


{
cout << "fun(const int) called ";
}
void fun(int i)
{
cout << "fun(int ) called " ;
}
int main()
{
const int i = 10; Compiler Error: redefinition of 'void fun(int) because
fun(i); it is call by value
return 0;
}
C++ allows functions to be overloaded on the
basis of const-ness of parameters only if the const
parameter is a reference or a pointer. That is why
the program 1 failed in compilation, but the
void fun(char *a) program 2 worked fine.
{
cout << "non-const fun() " << a;
}

void fun(const char *a)


{
cout << "const fun() " << a;
}

int main()
{
const char *ptr = "GeeksforGeeks";
fun(ptr);
return 0;
}
Output:

const fun() GeeksforGeeks


Write C++ program to find the area of various 2D shapes
such as square, rectangle, triangle and circle using
function overloading
#include<iostream>
using namespace std;
class shape
{
public:
float area(float r);
int area(int s);
int area(int l,int w);
float area(float b,float h);

};
int shape:: area(int s)
{
return(s*s);
}
int shape ::area(int l,int b)
{
return(l*b);
}
float shape::area(float r)
{
return(3.14*r*r);
}

float shape::area(float bs,float ht)


{
return((bs*ht)/2);
}
int main()
{
int s,l,b;
float r,bs,ht;
shape ob;
cout<<"Enter side of a square:";
cin>>s;
cout<<"Enter length and breadth of rectangle:";
cin>>l>>b;
cout<<"Enter radius of circle:";
cin>>r;
cout<<"Enter base and height of triangle:";
cin>>bs>>ht;
cout<<"Area of square is"<<ob.area(s);
cout<<"\nArea of rectangle is "<<ob.area(l,b);
cout<<"\nArea of circle is "<<ob.area(r);
cout<<"\nArea of triangle is "<<ob.area(bs,ht);
}
Example of function overloading
#include<string. h>
#include <iostream.h>
class complex
{
int r;
int i;
public:
complex()
{ r=0; i=0; }
complex(int a,int b)
{
r=a; i=b; }
complex add_complex(complex);
void add_complex(int);
void add_complex(complex,complex);
void display(){ cout<<"real"<<r<<"imaginary"<<i<<endl;} };
complex complex::add_complex(complex o)
{
complex temp;
temp.r=r+o.r;
temp.i=i+o.i;
return temp;
}
void complex::add_complex(int c)
{
r=r+c;
i=i+c;
}
void complex::add_complex(complex o1, complex o2)
{
r=o1.r+o2.r;
i=o1.i+o2.i;
}
int main()
{
complex c1(2,3),c2(4,5);
complex c3,c4;
c3=c1.add_complex(c2);
c1.add_complex(5);
c4.add_complex(c1,c2);
c3.display();
c4.display();
return 0;}
Overloaded constructor
• When a dynamic array of class will be allocated. Dynamic array can not be initialized
• If class contain a constructor that takes an initializer, you must include an overloaded version that takes no
initialize
class myclass
{
int x;
public:
myclass(){ x=0;}
myclass(int n){x=n;}
};
myclass *p;
p=new myclass[10];
Default arguments
• Related to function overloading
• Allows you to give a parameter a default value when no corresponding argument is
specified when the function is called
• It is a shorthand form of function overloading
• Specified when function is declared.it must be specified only once either in the prototype
or in definition if the definition proceeds the first use
• E.g. void f(int a=0,int b=0)
• Three ways it can be called
• f(); a=0 b=0
• f(10) a=10 b=0
• F(10,20) a=10 b=20
• Only trailing arguments can have default values so we must add defaults from right to left.
• In other word one you specify argument default all the arguments which are right to it
must have default
• int mul(int I,int j=5; int k=10); legal
• int mul(int i=5; int j); illegal
• int mul(int i=10; int j; int k=20); illegeal
• int mul(int i=2;int j=5; int k=10); legal
double rect_area(double l, double w=0)
{
if(!w)
w=l;
return l*w;}
int main()
{
cout<<rect_area(10.5,5.8)<<endl;
cout<<rect-area(10.00)<<endl;
return 0;
}
Constructor with default arguments
class myclass
{
int x;
public:
myclass(int n=0)
{
x=n;}
int getx(){ return x;}
int main()
{
myclass o1(10);
myclass o2;
cout<<o1.getx()<<endl;
cout<<o2.getx()<<endl;
return 0;}
Ambiguity
int f(int a)
{
return a*a;
}
Int f(int a, int b=0)
{
return a*b;
}
int main()
{
cout<<f(10,2);
cout<<f(10); //ambiguity
}
Create a function called reverse() that takes two parameters. The first parameter,
called str is a pointer to a string that will be reversed upon return from the
function. The second parameter is called count and specify how many characters
of str to reverse. When not specified it reverse entire string.
• class room
int main()
• { {
• int width, height; room ob(10,20);
• public: ob.display();
• room(int x,int y=0) cout<<ob.area();
• { room ob1(30);
• width=x; ob1.display();
• height=y; cout<<ob.area();
• } }
• void display()
• {
• cout<<width<<" "<<height<<endl;
• }
• int area()
• {

• return width*height;
• }
• };
#include<iostream.h>
class exam
{
int a;
int b;
public:
int c;
void exam(int i, int j=0,int k)
{
a=i;
b=j;
c=k;
}
void display()
{
cout<<"a= "<<a<<"b= "<<b<<"c= "<<c<<endl;
}
};
int main()
{
exam e1(2);
exam e2(3,4);
exam e3(5,6,7);
e1.display(); e2.display(); e3.display(); return 0; }
#include<iostream>
#include<cstring> else
using namespace std; {
void reverse( char *s, int count=0) int i;
{ int len=strlen(s);
if(count==0) for( i=0;i<count; i++)
{ {
int len=strlen(s); char c=s[i];
int i; s[i]=s[len-1-i];
for( i=0;i<len/2; i++) s[len-1-i]=c;
{ }
char c=s[i];
s[i]=s[len-1-i]; }
s[len-1-i]=c; }
} int main()
} {
char *st=new char[10];
strcpy(st,"sardar");
reverse(st,2);
cout<<st;
}
void change(char *s)
Copy object {
strcpy(p,s);
• #include<string.h> }
void display(){ cout<<p<<endl;}
• #include <iostream.h> ~samp(){cout<<"destructor\n";delete [] p;}
• #include <conio.h> };
• class samp
• {
• char *p; int main()
• public: {
• samp() clrscr();
• { samp s1("hello");
samp s2("how");
• p='\0';} samp s3;
• samp(char *s) s3=s1;
• { s3.display();
• int l; s1.change("bvm");
s1.display();
• l=strlen(s); s2.display();
• p=new char[l+1]; s3.display();
• strcpy(p,s); return 0; }
• }
class samp
C++ prog to concate two strings
{
char *p;
public:
samp()
{
p='\0';}
samp(char *s)
{
int l;
l=strlen(s);
p=new char[l+1];
strcpy(p,s);
}
samp concate(samp s1);
void display(){ cout<<p<<endl;}
~samp(){cout<<"destructor\n";delete [] p;}
samp samp::concate(samp s)
{
samp c1;
int l;
l=strlen(s.p)+strlen(p);
c1.p=new char[l+1];
strcpy(c1.p,p);
strcat(c1.p,s.p);
return c1;
}

int main()
{
clrscr();
samp s1("hello");
samp s2("how");
samp s3=s1.concate(s2);
//s3=s1.concate(s2);
s3.display();
return 0;
Discussion
• When object is passed by value bitwise copy of all the data members
is made
• Problem comes when object member is pointer and dynamic memory
is allocated.
• In this case only address is copy so both object pointer data member
point to same memory
• Problems occur when object is passed to or returned from a function
• Here destructor try to free an already released piece of memory.so
you may get null pointer assignment message
Solution

• Instead of call by value use call by reference


• void samp::concate(samp &s2,samp &s3)
• {
• int l;
• l=strlen(s2.p)+strlen(p);
• s3.p=new char[l+1];
• strcpy(s3.p,p);
• strcat(s3.p,s2.p);
• }

• s1.concate(s2,s3); calling from main


Second solution is used copy
constructor
• It is an overloaded constructor
• By defining a copy constructor you can fully specify exactly what
occurs when copy of an object is made
• The value of one object is given to another : assignment and
initialization
• Copy constructor only invokes when initialization takes place
Three cases
• When an object is used to initialize another in a declaration statement
• When an object is passed as a parameter to a function
• When temporary object is created for use as a return value by
function
Note : not invoked in case of assignment
Copy constructor
• common form of copy constructor
• classname(const classname &obj)
• myclass x=y
• func1(y)
• y=fun2(z)
Why argument to a copy constructor must be passed as a reference?
A copy constructor is called when an object is passed by value. Copy constructor itself is a
function. So if we pass an argument by value in a copy constructor, a call to copy constructor
would be made to call copy constructor which becomes a non-terminating chain of calls.
Therefore compiler doesn’t allow parameters to be passed by value.
Copy constructor
class myclass Use of copy constructor at the time of
{ initialization
int *p;
public:
myclass();
myclass(const myclass &);
//myclass f();
~myclass(){cout<<"destrucotr\n";delete [] p;}
void display(){ for(int i=0;i<3;i++)
cout<<p[i]<<endl;}
};
int main()
myclass::myclass() {
{ clrscr();
myclass ob1,ob2;
cout<<"constructor\n"; cout<<"ob2 object\n";
p=new int[3]; ob2.display();
for(int i=0;i<3;i++) myclass ob3=ob1;
cout<<"ob3 object\n";
cin>>p[i]; ob3.display();
} ob1=ob2;
cout<<"ob1 changed but not
myclass::myclass(const myclass &o) ob3\n";
{ ob1.display();
cout<<" copy constructor\n"; ob3.display();
return 0; }
p=new int[3];
for(int i=0;i<3;i++)
p[i]=o.p[i];
}
output
• class samp
• { Copy constructor when object pass as
• char *p; parameter
• public:
• samp()
• {
• p='\0';}
• samp(char *s)
• {
• int l;
• l=strlen(s);
• p=new char[l+1];
• strcpy(p,s);

• }
• samp(const samp &s);
• char *get(){ return p; }
• ~samp(){cout<<"destructor\n";delete [] p;}
• };
samp::samp(const samp &o)

{
int l;
cout<<“copy const\n”;
l=strlen(o.p)+1;
p=new char [l];
strcpy(p,o.p);
}
void show(samp x)
{
char *s;
s=x.get();
cout<<s<<endl;
}

int main()
{
clrscr();
samp a("hello"),b("there");
show(a);
show(b);
return 0;
}
output
myclass::myclass()
{

Function returning object


cout<<"constructor\n";
p=new int[3];
for(int i=0;i<3;i++)
• class myclass cin>>p[i];
}
• { myclass::myclass(const myclass &o)
• int *p; {
cout<<" copy constructor\n";
• public: p=new int[3];
• myclass(); for(int i=0;i<3;i++)
p[i]=o.p[i];
• myclass(const myclass &); }
• myclass f(); myclass myclass::f()
{
• ~myclass(){cout<<"destrucotr\n";delete [] p;}
myclass temp;
• void display(){ for(int i=0;i<3;i++) return temp; }
• cout<<p[i]<<endl;}
• };
int main()
{
myclass ob1,ob2;
ob2.display();
ob2=ob1.f();
ob2.display();
return 0; }
output
class samp
samp samp::concate(samp s)
{
{
char *p;
samp c1;
public:
int l;
samp()
l=strlen(s.p)+strlen(p);
{
c1.p=new char[l+1];
p='\0';}
strcpy(c1.p,p);
samp(char *s)
strcat(c1.p,s.p);
{
return c1;
int l; int main()
}
l=strlen(s); {
samp::samp(const samp &o)
p=new char[l+1]; clrscr();
{
strcpy(p,s); samp s1("hello");
cout<<“copy const\n”;
} samp s2("how");
len=strlen(o.p);
samp concate(samp s1); // samp s3;
p=new char[len+1];
samp(const samp&); samp s3=s1.concate(s2);
strcpy(p,o.p);
void display(){ cout<<p<<endl;} s3.display();
~samp(){cout<<"destructor\n";delete [] p;} return 0; }
}
};

Concantation of two string


class Simple {
private:
int* data;

public:
// Constructor
Simple(int value) : data(new int(value))
{
cout << "Constructor called, data = " << *data
<< endl;
}

Simple(Simple&& other)
: data(other.data)
{
// nullify the other object resource
other.data = nullptr;
cout << "Move constructor called" << endl;
}

You might also like