Overloading Constructors and Finding the Address of an Overloaded Function
This lecture covers two related but distinct C++ concepts: constructor
overloading, which provides multiple ways to initialize objects, and finding
the address of an overloaded function, which requires the compiler to
identify the exact function version before its address can be stored.
1. Overloading Constructors
1.1 Introduction
A constructor is a special member function of a class
that is automatically called when an object of that class is created. A
constructor has the same name as the class and does not have a return type.
C++ allows a class to contain more than one constructor,
provided that their parameter lists are different. This is called constructor
overloading.
Constructor overloading allows objects of the same class to
be initialized in different ways.
For example, a class may provide:
- a
constructor with no arguments,
- a
constructor with one or more arguments,
- a
copy constructor.
The compiler determines which constructor to invoke based on
the arguments supplied during object creation.
Figure 1: Constructor Overloading
1.2 Basic Syntax
A class can contain multiple constructors as follows:
class ClassName
{
public:
ClassName(); // Default constructor
ClassName(int
x); // Parameterized
constructor
ClassName(int x,
int y); // Parameterized constructor
ClassName(const
ClassName &obj); // Copy
constructor
};
The constructors have the same name, but their
parameter lists are different.
1.3 How Constructor Overloading Works
Consider:
Student s1;
Student s2(101);
Student s3(101, 85);
The compiler selects the constructor according to the
arguments:
|
Object creation |
Constructor selected |
|
Student s1; |
Student() |
|
Student s2(101); |
Student(int) |
|
Student s3(101, 85); |
Student(int, int) |
Thus, constructor overloading provides multiple
initialization mechanisms within the same class.
2. Program Example: Overloading Constructors
#include <iostream>
#include <string>
using namespace std;
class Student
{
int rollNo;
string name;
public:
// Default
constructor
Student()
{
rollNo = 0;
name =
"Not Assigned";
cout <<
"Default constructor called" << endl;
}
// Parameterized
constructor
Student(int r,
string n)
{
rollNo = r;
name = n;
cout <<
"Parameterized constructor called" << endl;
}
// Copy
constructor
Student(const
Student &obj)
{
rollNo =
obj.rollNo;
name =
obj.name;
cout <<
"Copy constructor called" << endl;
}
void display()
{
cout <<
"Roll Number: " << rollNo << endl;
cout <<
"Name: " << name << endl;
}
};
int main()
{
Student s1;
cout <<
endl;
Student s2(101,
"Krishna");
cout <<
endl;
Student s3 = s2;
cout <<
"\nStudent 1:" << endl;
s1.display();
cout <<
"\nStudent 2:" << endl;
s2.display();
cout <<
"\nStudent 3:" << endl;
s3.display();
return 0;
}
Expected Output
Default constructor called
Parameterized constructor called
Copy constructor called
Student 1:
Roll Number: 0
Name: Not Assigned
Student 2:
Roll Number: 101
Name: Krishna
Student 3:
Roll Number: 101
Name: Krishna
2.1 Explanation
Three objects are created in the program.
Object 1
Student s1;
No argument is supplied, so the compiler calls:
Student()
This is the default constructor.
Object 2
Student s2(101, "Krishna");
Two arguments are supplied. Therefore, the compiler selects:
Student(int r, string n)
This constructor initializes the object with the supplied
values.
Therefore:
rollNo = 101
name = Krishna
Object 3
Student s3 = s2;
Here, s3 is initialized using an existing object s2.
Therefore, the copy constructor is invoked:
Student(const Student &obj)
The values of s2 are copied into s3.
3. Important Rules of Constructor Overloading
Rule 1: Constructors must have the class name
class Student
{
public:
Student();
};
Rule 2: Constructors do not have a return type
Incorrect:
int Student();
Correct:
Student();
Rule 3: Parameter lists must differ
Valid:
Student();
Student(int);
Student(int, int);
Invalid:
Student(int);
Student(int);
Two constructors cannot differ only in their return type
because constructors do not have return types.
Rule 4: The compiler selects the constructor based on
arguments
Student s1;
// Student()
Student s2(10);
// Student(int)
Student s3(10, 20);
// Student(int, int)
4. Constructor Overloading vs Function Overloading
Constructor overloading is actually a special application of
the general concept of function overloading.
|
Function Overloading |
Constructor Overloading |
|
Multiple functions have the same name |
Multiple constructors have the same class name |
|
Parameter lists must differ |
Parameter lists must differ |
|
Function may return a value |
Constructor has no return type |
|
Called explicitly |
Called automatically during object creation |
|
Example: sum() |
Example: Student() |
5. Finding the Address of an Overloaded Function
5.1 Introduction
C++ allows us to obtain the address of a function and store
it in a function pointer.
For a non-overloaded function, the process is
straightforward:
void show(int x)
{
cout << x;
}
void (*ptr)(int) = show;
However, the situation becomes different when functions are overloaded.
Consider:
void show(int);
void show(double);
Both functions have the same name:
show
but they have different parameter lists.
Therefore, simply writing:
ptr = show;
may not provide enough information to determine which
overloaded function is intended.
The function pointer's type is used to identify the required
overloaded version.
Figure 2: Finding the Address of an Overloaded Function
6. Function Pointer
A function pointer is a pointer that stores the
address of a function.
General Syntax
return_type (*pointer_name)(parameter_list);
For example:
void (*ptr)(int);
This means that ptr can store the address of a function
that:
- returns
void, and
- accepts
one int argument.
7. Address of an Overloaded Function
Suppose we have:
void show(int x)
{
cout <<
"Integer: " << x;
}
void show(double x)
{
cout <<
"Double: " << x;
}
There are two functions named show.
To obtain the address of the integer version:
void (*ptr)(int) = show;
The compiler sees that ptr can point only to:
void show(int)
Therefore, that overloaded function is selected.
Similarly:
void (*ptr)(double) = show;
selects:
void show(double)
8. Program Example: Address of an Overloaded Function
#include <iostream>
using namespace std;
void show(int x)
{
cout <<
"Integer version: " << x << endl;
}
void show(double x)
{
cout <<
"Double version: " << x << endl;
}
void show(int x, int y)
{
cout <<
"Two integer version: "
<< x
<< " " << y << endl;
}
int main()
{
// Pointer to
show(int)
void (*ptr1)(int)
= show;
// Pointer to
show(double)
void
(*ptr2)(double) = show;
// Pointer to
show(int, int)
void (*ptr3)(int,
int) = show;
// Calling
functions through pointers
ptr1(10);
ptr2(5.5);
ptr3(10, 20);
return 0;
}
Output
Integer version: 10
Double version: 5.5
Two integer version: 10 20
9. Explanation of the Program
Three overloaded functions are defined:
void show(int x)
void show(double x)
void show(int x, int y)
All three functions have the same name, but their parameter
lists are different.
Step 1: Integer version
void (*ptr1)(int) = show;
The pointer ptr1 accepts a function having the signature:
void(int)
Therefore, it points to:
show(int)
Step 2: Double version
void (*ptr2)(double) = show;
The pointer ptr2 accepts:
void(double)
Therefore, the compiler selects:
show(double)
Step 3: Two-integer version
void (*ptr3)(int, int) = show;
The required function must have the signature:
void(int, int)
Therefore:
show(int, int)
is selected.
Step 4: Calling through pointers
The functions can now be called through the respective
pointers:
ptr1(10);
ptr2(5.5);
ptr3(10, 20);
Thus, the function pointer provides an indirect way of
calling the selected overloaded function.
10. Function Signature and Overload Resolution
The compiler distinguishes overloaded functions using their parameter
lists.
For example:
void calculate(int);
void calculate(double);
void calculate(int, int);
Their signatures, for overload-resolution purposes, are
different because their parameter lists differ.
The function pointer must therefore have a compatible type.
void (*p1)(int) = calculate;
void (*p2)(double) = calculate;
void (*p3)(int, int) = calculate;
Conceptual understanding
Overloaded Function Name
"calculate"
|
┌─────┼─────┐
↓ ↓
↓
int double
int,int
| |
|
↓ ↓
↓
p1 p2
p3
In an actual C++ implementation, the compiler uses the
pointer's function type to resolve which overloaded function is intended.
11. Another Example Using static_cast
In some situations, the desired overloaded function can be
explicitly selected using static_cast.
#include <iostream>
using namespace std;
void display(int x)
{
cout <<
"Integer: " << x << endl;
}
void display(double x)
{
cout <<
"Double: " << x << endl;
}
int main()
{
void (*ptr)(int);
ptr = static_cast<void
(*)(int)>(display);
ptr(25);
return 0;
}
Output
Integer: 25
Here, the cast explicitly specifies that the required
function has the type:
void(int)
Therefore, the compiler selects:
display(int)
12. Important Points
Constructor Overloading
- A
class can contain multiple constructors.
- All
constructors have the same name as the class.
- Their
parameter lists must be different.
- Constructors
do not have return types.
- The
compiler selects the appropriate constructor during object creation.
- Constructor
overloading provides multiple ways of initializing objects.
Address of an Overloaded Function
- A
function address can be stored in a function pointer.
- An
overloaded function name alone may be ambiguous when assigning its
address.
- The
function pointer's type helps identify the required overloaded function.
- The
number and types of parameters must match the pointer's function type.
- static_cast
can be used when explicit disambiguation is required.
13. Common Mistakes
Mistake 1: Defining two identical constructors
Student(int x);
Student(int y);
This is not constructor overloading because both have
the same parameter type:
Student(int)
The parameter names x and y do not make the signatures
different.
Mistake 2: Using a return type with a constructor
Incorrect:
void Student();
A constructor must not have a return type.
Correct:
Student();
Mistake 3: Assigning an overloaded function without
resolving the required type
For example:
void show(int);
void show(double);
auto ptr = show;
The compiler may not have sufficient information to
determine which overloaded function is intended.
Instead, provide the function pointer type:
void (*ptr)(int) = show;
14. Key Points for Students
- Constructor
overloading means defining multiple constructors with different
parameter lists.
- The
compiler selects the constructor according to the arguments supplied
during object creation.
- Default,
parameterized, and copy constructors can coexist in the same class.
- A
function pointer stores the address of a function.
- An
overloaded function has multiple versions with the same name.
- The
function pointer type can identify the required overloaded function.
- The
number and types of parameters must be compatible with the function
pointer.
- static_cast
can explicitly select a particular overloaded function.
Exam-Oriented Definitions
Constructor Overloading:
Constructor overloading is the process of defining multiple constructors within
the same class with different parameter lists so that objects can be
initialized in different ways.
Function Pointer:
A function pointer is a pointer variable that stores the address of a function
and can be used to invoke that function indirectly.
Finding the Address of an Overloaded Function:
It is the process of obtaining the address of a specific overloaded function by
providing sufficient type information, generally through a compatible
function-pointer type or an explicit cast.
No comments:
Post a Comment