In this lesson, you will learn
Generic classes are useful when a class uses logic that can be generalized. For Example, The same algorithms which is maintaining a queue of integers will also work for a queue of characters.
Class templates are generally used for data storage (container) classes. The major examples, you will see in the next chapter i.e. Standard Template Library (STL).
Let us create a Stack class that stores data only of type int.
class Stack
{
private:
int st[MAX]; //array of ints
int top; //index number of top of stack
public:
Stack(); //constructor
void push(int var); //takes int as argument
int pop(); //returns int value
};
If we wanted to store data of type long in a stack, we would need to define a completely separate class such as
class LongStack
{
private:
long st[MAX]; //array of longs
int top; //index number of top of stack
public:
LongStack(); //constructor
void push(long var); //takes long as argument
long pop(); //returns long value
};
Similarly, you need to create a new stack class for every data type we want to store.
It would be nice if you would be able to write a single class specification that would work for variables of all types, instead of a single basic type.
As you may have guessed, class templates allow us to do this. So, let’s learn the class templates.
Here’s a general structure:
template<typename T>
class ClassName {
T member; // 'T' can be any data type
public:
ClassName(T arg) : member(arg) {} // Constructor accepting type T
T getMember() { return member; } // Method using type T
};
template <typename T>
template
keyword tells the compiler that the following class is a template.typename T
(or alternatively class T
) declares T
as a placeholder for a type. You can use any name instead of T
, but T
is conventional.T
can be any type (like int
, double
, string
, or even another class).class ClassName
T
as a placeholder for any data type.T
T
is used wherever you would normally specify a data type. This makes the class generic.Once you have created a generic class, you create a specific instance of that class using the following general form:
class-name<T> ob;
Here, T is the type name of the data that the class will be operating upon.
Note: Member functions of a generic class are themselves automatically generic. You need not use the template to explicitly specify them as such.
You can have multiple types as parameters if needed:
template<typename T, typename U>
class ClassName {
// Class definition using 'T' and 'U' as placeholders for data types
};
In this case, T and U are different placeholders that allow the class to handle more than one type.
Here’s a simple example using a class template for storing a single item of any data type:
#include<iostream>
using namespace std;
template<typename T>
class Box {
T content;
public:
Box(T c) : content(c) {}
T getContent() { return content; }
};
int main() {
Box intBox(123); // Box for integers
Box doubleBox(45.67); // Box for doubles
Box stringBox("Hello"); // Box for strings
cout << "Int Box: " << intBox.getContent() << endl;
cout << "Double Box: " << doubleBox.getContent() << endl;
cout << "String Box: " << stringBox.getContent() << endl;
return 0;
}
You can also define templates with more than one type parameter:
#include<iostream>
using namespace std;
template<typename T, typename U>
class Pair {
T first;
U second;
public:
Pair(T a, U b) : first(a), second(b) {}
void display() {
cout << "First: " << first << ", Second: " << second << endl;
}
};
int main() {
Pair<int, double> p1(10, 20.5);
Pair<string, char> p2("Hello", 'A');
p1.display();
p2.display();
return 0;
}
Function templates enable you to write a generic function that can work with any data type.
#include<iostream>
using namespace std;
// Function Template
template<typename T>
T getMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
int intMax = getMax(10, 20); // Works with int
double doubleMax = getMax(10.5, 7.8); // Works with double
char charMax = getMax('a', 'z'); // Works with char
cout << "Max of 10 and 20 is: " << intMax << endl;
cout << "Max of 10.5 and 7.8 is: " << doubleMax << endl;
cout << "Max of 'a' and 'z' is: " << charMax << endl;
return 0;
}
Max of 10 and 20 is: 20
Max of 10.5 and 7.8 is: 10.5
Max of 'a' and 'z' is: z
getMax
is a generic function that can operate on any data type (like int
, double
, char
).template <typename T>
is the template definition, where T
is a placeholder for any data type.T
based on the function call.getMax(10, 20)
treats T
as int
.getMax(10.5, 7.8)
treats T
as double
.getMax('a', 'z')
treats T
as char
.
A more complex example involves a stack that can work with any data type:
//ClassTemplatesEx1.cpp
#include<iostream>
using namespace std;
const int MAX = 100; //size of array
template <class Type>
class Stack
{
private:
Type st[MAX]; //stack: array of any type
int top; //number of top of stack
public:
Stack() //constructor
{ top = -1; }
void push(Type var) //put number on stack
{ st[++top] = var; }
Type pop() //take number off stack
{ return st[top--]; }
};
int main()
{
Stack<float> s1; //s1 is object of class Stack<float>
s1.push(11.1F); //push 3 floats, pop 3 floats
s1.push(22.2F);
s1.push(33.3F);
cout<<"1: "<<s1.pop()<<endl;
cout<<"2: "<<s1.pop()<<endl;
cout<<"3: "<<s1.pop()<<endl;
Stack<long> s2; //s2 is object of class Stack<long>
s2.push(123123123L); //push 3 longs, pop 3 longs
s2.push(234234234L);
s2.push(345345345L);
cout<<"1: "<<s2.pop()<<endl;
cout<<"2: "<<s2.pop()<<endl;
cout<<"3: "<<s2.pop()<<endl;
return 0;
}
1: 33.3
2: 22.2
3: 11.1
1: 345345345
2: 234234234
3: 123123123
#include<iostream>
using namespace std;
template<typename T>
class Stack {
T arr[10]; // Fixed-size stack for simplicity
int top;
public:
Stack() : top(-1) {}
void push(T value) {
if (top < 9) {
arr[++top] = value;
} else {
cout << "Stack overflow!" << endl;
}
}
T pop() {
if (top >= 0) {
return arr[top--];
} else {
cout << "Stack underflow!" << endl;
return T(); // Return a default-constructed object
}
}
};
int main() {
Stack<int> intStack;
intStack.push(5);
intStack.push(10);
cout << "Popped from int stack: " << intStack.pop() << endl;
Stack<string> stringStack;
stringStack.push("Hello");
stringStack.push("World");
cout << "Popped from string stack: " << stringStack.pop() << endl;
return 0;
}
Popped from int stack: 10
Popped from string stack: World
Error in example 2: A Template Class for a Simple Stack–>Interger and string specific instance of template have not been created
best content
You must be logged in to submit a review.