Mastering C++ Class Templates: A Practical Guide
Mastering C++ Class Templates: A Practical Guide
Learn how to leverage C++ class templates to write flexible, type‑agnostic code with clear, real‑world examples.
Templates are a cornerstone of generic programming in C++. They let you create reusable components that work with any data type, improving code clarity and reducing duplication. C++ offers two kinds of templates: function templates and class templates.
- Function Templates
- Class Templates
Class templates enable you to define a single class that adapts to multiple data types. This not only shortens your code but also makes it easier to maintain.
Declaring a Class Template
A class template begins with the template keyword, followed by a list of template parameters enclosed in angle brackets. After that comes the actual class definition.
template <class T>
class MyClass {
private:
T var;
public:
T getVar() const;
};
Here, T is a placeholder for the data type that will be supplied when the template is instantiated. The keyword class can be replaced with typename without changing semantics.
Instantiating a Class Template
Once a template is defined, you can create objects by specifying the desired type:
MyClass<int> intObj;
MyClass<float> floatObj;
MyClass<std::string> stringObj;
Each instantiation generates a concrete class tailored to the specified type during compilation.
Example 1: Generic Number Wrapper
#include <iostream>
using namespace std;
// Class template that stores a single value of any type
template <class T>
class Number {
private:
T value;
public:
Number(T v) : value(v) {}
T getValue() const { return value; }
};
int main() {
Number<int> intNum(7);
Number<double> doubleNum(7.7);
cout << "int Number = " << intNum.getValue() << endl;
cout << "double Number = " << doubleNum.getValue() << endl;
return 0;
}
Output
int Number = 7 double Number = 7.7
Notice that the template parameter T is used for the member variable, constructor argument, and return type, allowing the class to work with any type.
Defining Members Outside the Class
When a member function is large or shared across specializations, you can define it outside the class body:
template <class T>
class Sample {
public:
T identity();
};
// Outside definition
template <class T>
T Sample<T>::identity() {
return static_cast<T>(1);
}
Note the repetition of the template<class T> declaration before the out‑of‑class definition.
Example 2: Calculator Using Class Templates
#include <iostream>
using namespace std;
template <class T>
class Calculator {
private:
T a, b;
public:
Calculator(T x, T y) : a(x), b(y) {}
T add() const { return a + b; }
T subtract() const { return a - b; }
T multiply() const { return a * b; }
T divide() const { return a / b; }
void display() const {
cout << "a: " << a << ", b: " << b << endl;
cout << "a + b = " << add() << endl;
cout << "a - b = " << subtract() << endl;
cout << "a * b = " << multiply() << endl;
cout << "a / b = " << divide() << endl;
}
};
int main() {
Calculator<int> intCalc(2, 1);
Calculator<float> floatCalc(2.4f, 1.2f);
cout << "Int results:\n";
intCalc.display();
cout << "\nFloat results:\n";
floatCalc.display();
return 0;
}
Output
Int results: a: 2, b: 1 a + b = 3 a - b = 1 a * b = 2 a / b = 2 Float results: a: 2.4, b: 1.2 a + b = 3.6 a - b = 1.2 a * b = 2.88 a / b = 2
Templates with Multiple Parameters
Class templates can accept more than one parameter, and you can even provide default types:
template <class T, class U, class V = int>
class MultiParam {
T first;
U second;
V third;
};
Example 3: Multi‑Parameter Template
#include <iostream>
using namespace std;
template <class T, class U, class V = char>
class ClassTemplate {
private:
T var1;
U var2;
V var3;
public:
ClassTemplate(T v1, U v2, V v3) : var1(v1), var2(v2), var3(v3) {}
void print() const {
cout << "var1 = " << var1 << endl;
cout << "var2 = " << var2 << endl;
cout << "var3 = " << var3 << endl;
}
};
int main() {
ClassTemplate<int, double> obj1(7, 7.7, 'c');
cout << "obj1 values:\n";
obj1.print();
ClassTemplate<double, char, bool> obj2(8.8, 'a', false);
cout << "\nobj2 values:\n";
obj2.print();
return 0;
}
Output
obj1 values: var1 = 7 var2 = 7.7 var3 = c obj2 values: var1 = 8.8 var2 = a var3 = 0
In this example, the third template parameter defaults to char, but can be overridden as shown with bool in obj2.
C Language
- C++ Classes & Objects: A Practical Guide to Object‑Oriented Programming
- Master C++ Inheritance: Build Powerful Classes with Reusable Code
- C++ Friend Functions and Friend Classes: Mastering Access Control
- Mastering C++ Virtual Functions: Concepts, Examples, and the Override Keyword
- Understanding Storage Classes in C++: Scope, Lifetime, and Usage
- Understanding Polymorphism in C++: A Practical Guide
- Mastering Data Abstraction in C++: Simplify Design with Interface-Implementation Separation
- Data Encapsulation in C++: Safeguard Your Code
- C++ Interfaces: Mastering Abstract Classes & Pure Virtual Functions
- Mastering C++ Templates: A Guide to Generic Programming