Unit -5 Generic function
Templates in C++
A template is a simple yet very powerful tool in C++, We can create a template
class, function, and variable. A template function is a function that can work with
any data type.
C++ adds two new keywords to support templates: ‘template’ and ‘typename’. The
second keyword can always be replaced by the keyword ‘class’.
Create a Function Template in C++
To create a template function in C++, we use the template keyword followed by
the typename keyword (or class keyword) and a placeholder for the type.
Syntax of Function Template
template<typename T>
returnType functionName(T parameter1, T parameter2, ...) {
// Body of the function
where:
template: This keyword can be used to declare the template
<typename T>: It can be used to declare the template parameter T.
returnType: This can be used to specify the return type.
T parameter1, T parameter: These are function parameters of type T.
// C++ Program to demonstrate
// Use of template
#include <iostream>
using namespace std;
// One function works for all data types. This would work
// even for user defined types if operator '>' is overloaded
template <typename T> T myMax(T x, T y)
return (x > y) ? x : y;
int main()
{ // Call myMax for int
cout << myMax<int>(3, 7) << endl;
// call myMax for double
cout << myMax<double>(3.0, 7.0) << endl;
// call myMax for char
cout << myMax<char>('g', 'e') << endl;
return 0;
Create a class Template in C++
n C++, class templates allow you to define a blueprint for creating classes or objects with generic types,
enabling code reuse and flexibility. Class templates are especially useful when the same class can be
applied to different data types, but the operations remain the same.
Syntax of a Class Template:
template <typename T>
class ClassName {
public:
T memberVariable;
ClassName(T param) : memberVariable(param) {}
void display() {
std::cout << "Value: " << memberVariable << std::endl;
}
};
Here, T is a template parameter representing a data type that will be provided when an object of this
class is instantiated
Example of a Class Template:
#include <iostream>
using namespace std;
template <typename T>
class Box {
private:
T value;
public:
Box(T v) : value(v) {}
void showValue() {
cout << "Value: " << value << endl;
};
int main() {
// Creating an object of the class template with int type
Box<int> intBox(100);
[Link]();
// Creating an object of the class template with string type
Box<string> strBox("Hello, C++ Templates!");
[Link]();
return 0;
}
Polymorphism in C++
The word “polymorphism” means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form.
Polymorphism is considered one of the important features of Object-Oriented Programming.
Types of Polymorphism
Compile-time Polymorphism
Runtime Polymorphism
1. Compile-Time Polymorphism
This type of polymorphism is achieved by function overloading or operator overloading.
1. Function Overloading
When there are multiple functions with the same name but different parameters, then the
functions are said to be overloaded, hence this is known as Function Overloading. Functions
can be overloaded by changing the number of arguments or/and changing the type of
arguments.
In simple terms, it is a feature of object-oriented programming providing many functions that
have the same name but distinct parameters
Advantages of Function Overloading in C++
Functional overloading save the memory space, consistency and
readability.
Code maintenance is easy.
It provides that load the class method based on the type of parameter.
Functional overloading speeds up the execution of the program.
It displays the behavior of polymorphism that allows us to get
different behavior, even though there will be some link using the
same name of the function.
Example
class Student
name, rollNumber, grade
Function Overloading setStudentInfo()-Default Value Set
setStudentInfo(string n, int r)
setStudentInfo(string n, int r, float g)
displayDetails()
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name; int
rollNumber;
double grade;
public:
// First overloaded function to set name, rollNumber, and grade (default values) void
setStudentInfo() {
name = "Rohan";
rollNumber = 1241;
grade = 9.06;
}
// Second overloaded function to set name and rollNumber void
setStudentInfo(string n, int r) {
name = n; rollNumber
= r;
// Grade can be set later, keeping it 0 for now
grade = 0;
}
// Third overloaded function to set name, rollNumber, and grade
void setStudentInfo(string n, int r, double g) {
name = n;
rollNumber = r;
grade = g;
}
// Function to display student information
void showStudentInfo() {
cout << "Name of Student: " << name << endl;
cout << "Roll Number of Student: " << rollNumber <<
endl; cout << "Grade of Student: " << grade << endl;
}
};
int main()
{ Student
S1; Student
S2; Student
S3;
// Call overloaded functions
[Link](); // Calls default info setter
[Link]("Aman", 21233); // Calls the second overloaded
function [Link]("Rohan", 34433, 8.7); // Calls the third overloaded
function
// Display student info
cout << "First Student Details:" << endl;
[Link]();
cout << "\nSecond Student Details:" << endl;
[Link]();
cout << "\nThird Student Details:" << endl;
[Link]();
return 0;
}
Constructors Overloading:
Constructor in C++ is a special method that is invoked automatically at the time an
object of a class is created. It is used to initialize the data members of new
objects generally. The constructor in C++ has the same name as the class or
structure. It constructs the values i.e. provides data for the object which is why it
is known as a constructor.
Characteristics of Constructors in C++
The name of the constructor is the same as its class name.
Constructors are mostly declared in the public section of the class though
they can be declared in the private section of the class.
Constructors do not return values; hence they do not have a return type.
A constructor gets called automatically when we create the object of the class
Class Student
Name, age , rollNo
Student()
Student(string n)
Student(string n, int a)
Student(string n, int a,
int r)
void display()
#include <iostream>
using namespace std;
class Student {
private:
string name;
int age;
int rollNo;
public:
// Default constructor
Student() {
name = "Unknown";
age = 0;
rollNo = 0;
}
// Constructor with one argument (name)
Student(string n) {
name = n;
age = 0;
rollNo = 0;
}
// Constructor with two arguments (name, age)
Student(string n, int a) {
name = n;
age = a;
rollNo = 0;
}
// Constructor with three arguments (name, age, rollNo)
Student(string n, int a, int r) {
name = n;
age = a;
rollNo = r;
}
// Function to display student details
void display() {
cout << "Name: " << name << ", Age: " << age << ", Roll No: " << rollNo << endl;
}
};
int main() {
// Creating objects using different constructors
Student s1; // Calls default constructor
Student s2("Alice"); // Calls constructor with one argument
Student s3("Bob", 20); // Calls constructor with two arguments
Student s4("Charlie", 22, 101); // Calls constructor with three arguments
// Displaying student details
[Link]();
[Link]();
[Link]();
[Link]();
return 0;
}
2. Operator Overloading
C++ has the ability to provide the operators with a special meaning
for a data type, this ability is known as operator overloading.
Operator overloading is a compile-time polymorphism. For example,
we can overload an operator ‘+’ in a class like String so that we can
concatenate two strings by just using +.
In C++, operator overloading can be classified into three categories:
Unary operators (like ++, --, -, etc.):
Operate on a single operand.
Example: Incrementing an object using ++.
Binary operators (like +, -, *, etc.):
Operate on two operands.
Example: Adding two complex numbers using +.
Special operators (like [], (), ->, new, etc.):
Provide special behaviors.
Example: Using [] for array subscript, () for function calls.
Let's look at examples of each category in C++.
1. Unary Operator Overloading Example (++ Operator)
The unary ++ operator and – operator is overloaded to increment and decrement a member of the
class.
#include <iostream>
using namespace std;
class Student {
private:
int marks;
public:
// Constructor to initialize marks
Student(int m) {
marks = m;
}
// Display the marks
void display() {
cout << "Marks: " << marks << endl;
}
// Overloading the unary ++ operator to increment marks
void operator ++ () {
++marks; // Pre-increment
}
// Overloading the unary -- operator to decrement marks
void operator -- () {
--marks; // Pre-decrement
}
};
int main() {
// Creating a Student object with marks
Student student(50);
cout << "Original Marks: ";
[Link]();
// Using the overloaded ++ operator (unary increment)
++student;
cout << "After Incrementing: ";
[Link]();
// Using the overloaded -- operator (unary decrement)
--student;
cout << "After Decrementing: ";
[Link]();
return 0;
}
2. Binary Operator Overloading Example (+ Operator)
#include <iostream>
using namespace std;
class Complex {
private:
float real;
float imag;
public:
// Constructor to initialize complex numbers
Complex(float r = 0, float i = 0) : real(r), imag(i) {}
// Overloading the + operator
Complex operator + (Complex obj) {
Complex result;
[Link] = real + [Link];
[Link] = imag + [Link];
return result;
}
// Function to display the complex number
void display() const {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
// Creating two complex number objects
Complex c1(3.2, 4.5);
Complex c2(1.3, 2.7);
// Adding the two complex numbers using overloaded + operator
Complex c3 = c1 + c2;
// Display the result
cout << "First Complex Number: ";
[Link]();
cout << "Second Complex Number: ";
[Link]();
cout << "Sum of the Complex Numbers: ";
[Link]();
return 0;
}
3. Special Operator Overloading Examples
Overloading [] (Array Subscript Operator)
#include <iostream>
using namespace
std; class Array {
private:
int arr[5];
public:
// Constructor to initialize array elements
Array() {
for (int i = 0; i < 5; i++)
arr[i] = i * 10;
}
// Overloading [] operator to access array elements
int& operator [] (int index) {
return arr[index];
}
};
int main() {
Array myArray;
cout << "Element at index 2: " << myArray[2] << endl; // Output: 20
// Using the overloaded [] operator to change array elements
myArray[2] = 50;
cout << "New element at index 2: " << myArray[2] << endl; // Output: 50
return 0;
}
Runtime Polymorphism
Virtual Function in C++
A virtual function (also known as virtual methods) is a member function that is
declared within a base class and is re-defined (overridden) by a derived class. When
you refer to a derived class object using a pointer or a reference to the base class,
you can call a virtual function for that object and execute the derived class’s
version of the method.
Virtual functions ensure that the correct function is called for an object,
regardless of the type of reference (or pointer) used for the function call.
They are mainly used to achieve Runtime polymorphism.
Functions are declared with a virtual keyword in a base class.
The resolving of a function call is done at runtime.
Rules for Virtual Functions
The rules for the virtual functions in C++ are as follows:
1. Virtual functions cannot be static.
2. A virtual function can be a friend function of another class.
3. Virtual functions should be accessed using a pointer or reference of base class
type to achieve runtime polymorphism.
4. The prototype of virtual functions should be the same in the base as well as the
derived class.
5. They are always defined in the base class and overridden in a derived class. It is
not mandatory for the derived class to override (or re-define the virtual
function), in that case, the base class version of the function is used.
6. A class may have a virtual destructor but it cannot have a virtual constructor.
// C++ program to illustrate
// concept of Virtual Functions
#include <iostream>
using namespace
std;
class base {
public:
virtual void print() { cout << "print base class\n"; }
void show() { cout << "show base class\n"; }
};
class derived : public base {
public:
void print() { cout << "print derived class\n"; }
void show() { cout << "show derived class\n"; }
};
int main()
{
base* bptr;
derived d;
bptr = &d;
// Virtual function, binded at
runtime bptr->print();
// Non-virtual function, binded at compile
time bptr->show();
return 0;
}
Pure virtual function:
A pure virtual function in C++ is a function that is declared in a base class but is meant to be overridden
in derived classes. It does not have any implementation in the base class and is assigned 0 in its
declaration to indicate that it is pure.
class Base {
public:
virtual void display() = 0; // Pure virtual function
};
Key Points:
1. Abstract Class: Any class that contains at least one pure virtual function becomes
an abstract class. You cannot create an object of an abstract class.
2. Must be Overridden: All derived classes must provide an implementation for the
pure virtual function, or they too will be considered abstract classes.
3. Purpose: Pure virtual functions enforce a common interface in derived classes
while allowing different implementations in each derived class.
#include <iostream>
using namespace
std;
class Shape {
public:
virtual void draw() = 0; // Pure virtual function
};
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing Circle" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "Drawing Rectangle" << endl;
}
};
int main() {
Shape* shape1 = new Circle();
Shape* shape2 = new Rectangle();
shape1->draw(); // Outputs: Drawing Circle
shape2->draw(); // Outputs: Drawing
Rectangle
delete shape1;
delete shape2;
return 0;
}
Templates in C++
A template is a simple yet very powerful tool in C++, We can create
a template class, function, and variable. A template function is a
function that can work with any data type.
C++ adds two new keywords to support
templates: ‘template’ and ‘typename’. The second keyword can always
be replaced by the keyword ‘class’.
Create a Function Template in C++
To create a template function in C++, we use the template keyword followed by the typename keyword
(or class keyword) and a placeholder for the type.
Syntax of Function Template
template<typename T>
returnType functionName(T parameter1, T parameter2, ...) {
// Body of the function
}
where:
template: This keyword can be used to declare the template
<typename T>: It can be used to declare the template parameter T.
returnType: This can be used to specify the return type.
T parameter1, T parameter: These are function parameters of type T.
// C++ Program to demonstrate
// Use of template
#include <iostream>
using namespace std;
// One function works for all data types. This would work
// even for user defined types if operator '>' is overloaded
template <typename T> T myMax(T x, T y)
return (x > y) ? x : y;
int main()
// Call myMax for int
cout << myMax<int>(3, 7) << endl;
// call myMax for double
cout << myMax<double>(3.0, 7.0) << endl;
// call myMax for char
cout << myMax<char>('g', 'e') << endl;
return 0;
Parametric polymorphism
Parametric polymorphism is all about executing the same code for any type. Templates are very good
example for the parametric polymorphism. One of the simplest example using templates is shown
Key Points about Parametric Polymorphism in C++:
1. Templates:
o Function Templates: These allow you to write a function that works with any data type.
o Class Templates: Similarly, class templates let you create a class that can handle
any data type.
2. Type Safety: Parametric polymorphism ensures type safety by allowing only
operations that are valid for all possible types.
3. Code Reusability: Templates make code more flexible and reusable because
they eliminate the need to write type-specific versions of the same function or
class.
Function Template
#include <iostream>
using namespace std;
template <typename T>
T add(T a, T b) {
return a + b;
int main() {
cout << "Int Addition: " << add(10, 20) << endl; // Works for int
cout << "Float Addition: " << add(5.5, 10.2) << endl; // Works for float
return 0;
Class Template
#include <iostream>
using namespace std;
template <typename T>
class Box {
T value;
public:
Box(T val) : value(val) {}
T getValue() { return value; }
};
int main() {
Box<int> intBox(100); // Box for integer
Box<string> strBox("Hello"); // Box for string
cout << "Int Box: " << [Link]() <<
endl;
cout << "String Box: " << [Link]() << endl;
return 0;
}
Advantages of Parametric Polymorphism:
Type Independence: Functions and classes can be written without specifying a concrete type,
allowing the same code to handle different data types.
Flexibility: Code becomes more flexible, and new types can be added easily without
rewriting the logic.
Efficiency: Since templates are resolved at compile time, the resulting code is highly efficient.
Difference between Compile Time and Run Time
Polymorphism (Imp)
Compile-Time Polymorphism Run-Time Polymorphism
It is also called Static Polymorphism. It is also known as Dynamic Polymorphism.
In compile-time polymorphism, the In run-time polymorphism, the decision of
compiler determines which function or which function to call is determined at runtime
operation to call based on the based on the actual object type rather than
number, types, and order of the reference or pointer type.
arguments.
Function calls are statically binded. Function calls are dynamically binded.
Compile-time Polymorphism can be
exhibited by: Run-time Polymorphism can be exhibited by
1. Function Overloading Function Overriding.
2. Operator Overloading
Faster execution rate. Comparatively slower execution rate.
Compile-Time Polymorphism Run-Time Polymorphism
Inheritance in not involved. Involves inheritance.