Chapter-14
Abu Saleh Musa Miah
M.Sc. Engg(On going)
University of Rajshahi
Function Overloading
Function overloading is the process of using the same name for two or more
functions.The secret to overloading is that each redefinition of the function must
use either different types of parameters or a different number of parameters.
It is only throughthese differences that the compiler knows which function to call
in any given situation.
int myfunc(int I
int myfunc(int i, int j);
int main()
{
cout << myfunc(10) << "
cout << myfunc(4, 5);
return 0;
}
int myfunc(int i)
{
return i;
}
int myfunc(int i, int
j)
{
return i*j;
}
Function Overloading
#include <iostream>
using namespace std;
int myfunc(int i);
double myfunc(double i);
int main()
{
cout << myfunc(10) << " ";
cout << myfunc(5.4);
return 0;
}
double myfunc(double i)
{
return i;
}
int myfunc(int i)
{
return i;
}
Overloading Constructor Functions:
Constructor functions can be overloaded.
There are three main reasons why you will want to overload a constructor
function:
 to gain flexibility,
 to allow both initialized and uninitialized
objects to be created, and
 to define copy constructors Overloading a
Constructor to Gain Flexibility Many times
you will create a class for which there are two
or more possible ways to construct an object
Overloading Constructor Functions:
The user is free to choose the best way to construct an object given the specific
circumstance.
class date {
int day, month, year;
public:
date(char *d);
date(int m, int d, int y);
void show_date();
};
date::date(char *d)
{
scanf(d, "c%d%*c%d%*c%d",
&month, &day, &year);
}
date::date(int m, int d, int y)
{
day = d;
month = m;
year = y; }
void date::show_date()
{
cout << month << "/" << day;
cout << "/" << year << "n";
}
int main() {
date ob1(12, 4, 2001),
ob2("10/22/2001");
ob1.show_date();
ob2.show_date();
return 0;
}
Copy Constructors:
One of the more important forms of an overloaded constructor is the copy
constructor. Defining a copy constructor can help you prevent problems that
might occur when one object is used to initialize another.
 when one object is used to initialize another, C++ performs a bitwise copy.
 there are situations in which a bitwise copy should not be used.
 One of the most common is when an object allocates memory when it is
created.
 For example, assume a class called MyClass that allocates memory for each
object when it is created, and an object A of that class. This means that A has
already allocated its memory. Further, assume that A is used to initialize B, as
shown here:
 MyClass B= A;
 If a bitwise copy is performed, then B will be an exact copy of A.
 if MyClass includes a destructor that frees the memory, then the same piece
of memory will be freed twice when A and B are destroyed
Copy Constructors:
 To solve the type of problem just described, C++ allows you to create a copy
constructor, which the compiler uses when one object initializes another. When
a copy constructor exists, the default, bitwise copy is bypassed.
 The most common generalform of a copy constructor is
classname (const classname &o) {
}
 Here, o is a reference to the object on the right side of the initialization. It is
permissible for a copy constructor to have additional parameters
 The copy constructor applies only to initializations.
myclass x = y; // y explicitly initializing x
func(y); // y passed as a parameter
y = func(); // y receiving a temporary, return object
Copy Constructors:
One of the more important forms of an overloaded constructor is the copy
constructor. Defining a copy constructor can help you prevent problems that
might occur when one object is used to initialize another.
when one object is used to initialize another, C++ performs a bitwise copy.
there are situations in which a bitwise copy should not be used.
One of the most common is when an object allocates memory when it is created.
#include <iostream>
using namespace std;
int myfunc(int i);
double myfunc(double i);
int main()
{
cout << myfunc(10) << " ";
cout << myfunc(5.4);
return 0;
}
double
myfunc(double i)
{
return i;
}
int myfunc(int i)
{
return i;
}
Finding the Address of an Overloaded Function:
If myfunc() is not overloaded, there is one and only one function called myfunc(),
and the compiler has no difficulty assigning its address to p. However, if
myfunc() is overloaded, how does the compiler know which version's address to
assign to p? The answer is that it depends upon how p is declared. For example,
consider this program:
#include <iostream>
using namespace std;
int myfunc(int a);
int myfunc(int a, int b);
int main()
{
int (*fp)(int a); // pointer to int
f(int)
fp = myfunc; // points to
myfunc(int)
cout << fp(5);
return 0;
}
int myfunc(int a)
{
return a;
}
int myfunc(int a, int b)
{
return a*b;
}
. In the program, fp is declared as a pointer to a function that returns an integer and that takes one
integer argument. When fp is assigned the address of myfunc() , C++ uses this information to select
the myfunc(int a) version of myfunc(). Had fp been declared like this:int (*fp)(int a, int b);
Default Function Arguments
C++ allows a function to assign a parameter a default value when no argument
corresponding to that parameter is specified in a call to that function. The default
value is specified in a manner syntactically similar to a variable initialization. For
example, this declares myfunc() as taking one double argument with a default
value of 0.0:
void myfunc(double d = 0.0)
{
// ...
}
Now, myfunc() can be called one of two
ways, as the following examples show:
myfunc(198.234); // pass an explicit value
myfunc(); // let function use default
#include <iostream>
using namespace std;
void clrscr(int size=25);
int main()
{
register int i;
for(i=0; i<30; i++ ) cout << i << endl;
cin.get();
clrscr(); // clears 25 lines
for(i=0; i<30; i++ ) cout << i << endl;
cin.get();
clrscr(10); // clears 10 lines
return 0;
}
void clrscr(int size)
{
for(; size; size--) cout << endl;
}
One reason that default arguments are included in C++ is because they provide another method for
the programmer to manage greater complexity. To handle the widest variety of situations, quite
frequently a function contains more parameters than are required for its most common usage
Default Arguments vs. Overloading:
In some situations, default arguments can be used as a shorthand form of function
overloading. The cube class's constructor just shown is one example.
Imagine that you want to create
two customized versions of the
standard strcat() function. The
first version will operate like
strcat() and concatenate the entire
contents of one string to the end of
another.
void mystrcat(char *s1, char *s2, int len);
void mystrcat(char *s1, char *s2);
1, len characters from s2 to the end of s1
2. s2 onto the end of the string pointed to by s1
Using Default Arguments Correctly Although default arguments can be a very powerful tool when used
correctly, they can also be misused. The point of default arguments is to allow a function to perform its job
in an efficient, easy-to-use manner while still allowing considerable flexibility. Toward this end, all default
arguments should reflect the way a function is generally used, or a reasonable alternate usage. When there
is no single value that is normally associated with a parameter, there is no reason to declare a default
argument. In fact, declaring default arguments when there is insufficient basis for doing so destructures
your code, because they are liable to mislead and confuse anyone reading your program.
Function Overloading and Ambiguity:
You can create a situation in which the compiler is unable to choose between two
(or more) overloaded functions. When this happens, the situation is said to be
ambiguous.Ambiguous statements are errors, and programs containing ambiguity
will not compile
#include <iostream>
using namespace std;
float myfunc(float i);
double myfunc(double i);
int main()
{
cout << myfunc(10.1) << " "; // unambiguous,
calls myfunc(double)
cout << myfunc(10); // ambiguous
return 0;
}
float myfunc(float i)
{
return i;
}
double myfunc(double i)
{
return -i;
}
Here, myfunc() is overloaded so that it can take arguments of either type float or type double. In the
unambiguous line, myfunc(double) is called because, unless explicitly specified as float, all floating-point
constants in C++ are automatically of type double.