Class Template Inheritance in C++
This article will discuss one of the most popular and frequently used methods in C++ (i.e., class templates).
The addition of templates to C++ ushered in a new coding paradigm known as Generic programming. This is now an important element of the C++ programmer’s toolkit, the foundation of much of the standard library, and something that many of us newer C++ hackers never encountered before.
Generic programming is sometimes contrasted with the concept of inheritance in object-oriented programming. On the other hand, a true multi-paradigm approach requires looking at how the two interact.
Templates in C++
In C++, a template is a basic but powerful tool. The basic idea is to pass the data type as a parameter, eliminating the need to write the same code for multiple data types.
A software business, for example, may require sort()
for many data kinds. Instead of writing and maintaining numerous codes, we can construct a single sort()
function and pass the data type as a parameter.
C++ added two new keywords to support templates: template
and typename
. The keyword class
can always be used in place of the second keyword.
Syntax:
template <typename T>
void myFunction(T var )
{
//function definition
}
In the shown above syntax, we can see that for defining a function that accepts a template variable as a parameter, we added a line template<typename T>
. Now, this function is eligible to accept a parameter of any data type; it is a generic function used for int, char, and many other data types.
How Templates Work in C++
Templates are expanded during the compilation process. This is similar to macros.
On the other hand, the compiler performs type checking before template expansion. The concept is straightforward: the source code only contains one function or class, whereas generated code may have numerous copies of the same function or class.
This is elaborated in the example below.
#include <iostream>
using namespace std;
template <typename T>
T checkMaxValue(T a, T b) {
if (a > b)
return a;
else if (b > a)
return b;
else
return 0;
}
// driver program
int main() {
cout << checkMaxValue(102, 204) << endl; // int value
cout << checkMaxValue('c', 'f') << endl; // char value
}
Note that we have passed two integers to the function in the first line of the driver program, and it will eventually return the max value integer among both. We have passed two char values to the same function on the second line, and the function will return the maximum char value.
At compile time, we call the function as shown below:
int checkMaxValue(int a, int b)
And for the second call, we write the following:
char checkMaxValue(char a, char b)
We can see that multiple copies of the same function are created at compile time depending on the type of variable passed when calling the function.
We can use templates for functions and classes. We will discuss both types and how to implement both.
Function Templates in C++
We will create a generic function that can work with various data kinds. Sort()
, max()
, min()
, and printArray
are examples of function templates.
Example code:
template <class T>
void sortArray(T arr[], int s) {
for (int i = 0; i < s - 1; i++)
for (int j = s - 1; i < j; j--)
if (arr[j] < arr[j - 1]) {
int var = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = var;
}
cout << " Sorted array : ";
for (int i = 0; i < s; i++) cout << arr[i] << " ";
cout << endl;
}
// Driver Code
int main() {
int a[5] = {10, 50, 30, 40, 20};
int n = 5;
sortArray<int>(a, n);
char c[5] = {'g', 'a', 'i', 'h', 'e'};
sortArray<char>(c, n);
return 0;
}
Output:
In the code snippet, we have created a function sortArray()
that can accept a template type of array and the size value of that array and print the sorted array. We have called it for two different array types in the main code: int and char arrays.
Consequently, we can use any data type, and the same function will work. It saves time and space and is also efficient in generic programming.
Class Templates in C++
Class templates, like function templates, are handy when a class has been defining something not dependent on the data type. LinkedList, BinaryTree, Stack, Queue, Array, and more classes may benefit from class templates.
Syntax:
template <class T>
class className {
private:
T a;
........public : T myFunc(T x);
........
};
In this syntax, T
is the template type used as a placeholder for the data type. When creating an object for this template class, the following syntax is used:
className<dataType> objectName;
Similarly, we may write it using this syntax:
className<int> objectName;
className<double> objectName;
Example:
#include <iostream>
using namespace std;
template <class T>
class Number {
private:
T numb;
public:
Number(T a) : numb(a) {}
T get() { return numb; }
};
int main() {
Number<int> integerNumber(50);
Number<double> doubleNumber(8.9);
cout << "integer Number = " << integerNumber.get() << endl;
cout << "double Number = " << doubleNumber.get() << endl;
return 0;
}
Output:
You can see in this example that the same class can accept an integer and a double number. This example is very generic to make you understand the concept of class templates.
This concept can be expanded, and many classes can be implemented using templates like LinkedList, Stack, Queue, etc.
Class Template Inheritance in C++
Inheriting from a template class is feasible. All regular inheritance and polymorphism rules apply.
If we need the new derived class to be general, we must make it a template class with a template argument sent to the base class. This is because inheritance is only possible with a class, and a template is not a class unless it is instantiated by passing some data type to it.
Syntax:
template <class T>
class derived : public Base<T>{};
Example:
#include <iostream>
using namespace std;
template <class T>
class Base {
private:
T val;
public:
void setVal(T a) { val = a; }
};
template <class T>
class Derived : public Base<T> {
public:
void setVal(T b) { Base<T>::setVal(b); }
};
int main() {
Derived<int> a;
a.setVal(4);
return 0;
}
We created a Base
class template containing a template type variable and a member function in the code snippet. Furthermore, we have created a derived class that is also a class template and extends the Base
class template.
When extending the Base
class, we must specify the template variable like Base<T>
. The Base
class is generic, and the derived class is also generic.
The derived class can have its template parameters as well. The previous example can be modified as follows:
template <class T, class S>
class Derived : public Base<T> {
private:
S data;
public:
void setVal(T b) {
Base<T>::setVal(b);
data = b;
}
};
So, we can see that inheritance can also be implemented using class templates. Moreover, we can implement polymorphism and adapter classes with class templates.
Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.
LinkedIn