Sie sind auf Seite 1von 10

1

Mekelle University Faculty of Business & Economics

Computer Science Department

ICT122: Object-Oriented Programming

Handout 4 – Templates

Handout Overview

In this handout the concept of templates in introduced. A single templated class or


function can have a number of different implementations, each of which works for a
different data type. Templates are the second way in which C++ provides
polymorphism.

1. What is a Template?

Sometimes you may need to write a number of functions or classes that are almost
identical, except with regard to the data types that they utilise. For example, you may
want to write one function that returns the maximum of two integer values, one
that returns the maximum of two double values, and another that returns the
maximum of two char values. To write three different functions seems like a waste
of effort. Also, if you want to make modifications to these functions in the future you
will have to make the modifications three separate times, instead of once.

Templates in C++ are designed to help you in situations like this. You can write a
single templated function or class, and then instantiate instances of it using a number
of different data types. For example, you can write a template function to calculate
the maximum of two values, without actually specifying what the data type of the
values will be. Then you can instantiate (i.e. create) three different versions of the
template function that take integer, double and char values respectively.

Used effectively, templates can save you time and make your code shorter and easier
to understand. There are two types of template: function templates and class
templates.

2. Function Templates

We will illustrate the concept of function templates with two examples: first a simple
example to show the syntax involved in defining templated functions, and then a
more realistic example.
2

2.1. A Simple Example

Consider the code below. This code is all contained within a single file called
“function_template.cpp”. Look first at the function prototype at the top of the file
just after the #include statement. The first line, template<class t>, tells
the compiler that this will be a templated function prototype. The identifier t is a
type template parameter: in other words, t will be considered to be a data type in
this prototype, but we will not specify yet precisely what type it will be. Bearing
this in mind, the second line, t max (t, t), is just a normal function
prototype. It defines a function called max that takes two values of type t and
returns a value of type t.

The function body for the max function is included at the end of the file. It is also
preceded by the line template<class t>, so again the identifier t is used to
represent the type parameter. The code for the max function is straightforward: it
compares the values of the two arguments a and b, and returns the greater of the
two. This templated function can therefore be used with any type of variable – the
only restriction is that the comparison operator > must be defined for the type.
This is true of all of the simple data types in C++ (char, int, float, etc.).

Now in the main function we can see that the max function is called twice: once
with two int arguments, and again with two char arguments. Each time a
function call is made the compiler will create an instantiation of the templated
function that works with the desired data type.

”function_template.cpp”

#include <iostream.h>

//template function prototype


template<class t>
t max (t, t);

main () {
//find maximum of two integers
int x, y;
x = 12;
y = 11;
cout << "Maximum of " << x << " and " << y
<< " is " << max(x, y) << endl;

//find maximum of two chars


char p, q;
p = 'w';
q = 'c';
cout << "Maximum of " << p << " and " << q
<< " is " << max(p, q) << endl;
}
3

//template function body


template<class t>
t max (t a, t b) {
if (a > b)
return a;
else
return b;
}

2.2. Insertion Sort Example

The previous example was very simple. In fact C++ comes with predefined
templated min and max functions so you don’t need to write your own – you just
need to #include <algorithm.h> at the beginning of your code.

The following example is more realistic. It is an implementation of a common


sorting algorithm known as insertion sort. Insertion sort is similar to the popular
bubble sort algorithm – at iteration i the task of the algorithm is to place the
i+1th element of the list in the correct place. It does this by comparing its value
with the previous i elements of the list (which have already been sorted), and
inserting it in the correct location. For example, given the simple integer list
below, the first iteration would try to find the correct location for the second
element, 5. It does this by comparing its value with the preceding elements, in this
case only the number 2. It finds that it is already in the correct position, and so
moves on to the second iteration. Next it tries to find the correct position for the
third element, 1. This should go right at the start of the list, so the algorithm shifts
the preceding elements forward one place, and inserts 1 at the beginning. This
process continues until the last element of the list has been inserted.

For a more detailed explanation of the insertion sort algorithm, see Cohoon &
Davidson (full reference given in the course outline), p482.

Consider the code below. The templated function sort takes two arguments: an
array of the type template parameter t, and an integer n, which indicates the
number of elements in the array argument. The function body implements the
insertion sort algorithm described above. Note here that we also use the type
template parameter t inside the function body, to declare a temporary variable
used when inserting the current list element.

Read the code carefully and make sure that you understand it. It may help if you
write down a simple list like the one given above and then step through the
program one statement at a time.
4

Question 1: are there any restrictions on what data types can be used with the
templated sort function? (see the end of this handout for the answer)

”insertion_sort.cpp”

#include <iostream.h>

//template function prototype


template<class t> void sort (t a[], int n);

main () {
int i;
// sort an integer array
int x[5] = {2, 1, 5, 3, 7};
cout << "Integer list before sorting\n";
for (i = 0; i < 5; i++)
cout << x[i] << " ";
cout << endl;
sort (x, 5);
cout << "Integer list after sorting\n";
for (i = 0; i < 5; i++)
cout << x[i] << " ";
cout << endl;
//sort a char array
char y[6] = {'c', 'e', 'a', 'd', 'b', 'f'};
cout << "Char list before sorting\n
for (i = 0; i < 6; i++)
cout << y[i] << " ";
cout << endl;
sort (y, 6);
cout << "Integer list after sorting\n";
for (i = 0; i < 6; i++)
cout << y[i] << " ";
cout << endl;
}

//function body
template<class t> void sort (t a[], int n) {
//look at every element apart from the first one
for (int i = 1; i < n; i++) {
//do we need to change this element's position?
if (a[i] < a[i-1]) {
//yes, so see where we should move it to
t value_i = a[i];
int j = i;
//keep moving it back in the list until we
//have found the right position
do {
a[j] = a[j-1];
j--;
} while ((j > 0) && (value_i < a[j-1]));
a[j] = value_i;
}
}
}
5

3. Class Templates

The second type of template you can define in C++ is a class template. Just as
function templates allow you to define a single function that can be instantiated many
times for different data types, so class templates allow you define a single templated
class that can be instantiated for different data types. Again we will look at two
examples to illustrate class templates. First we will consider a simple example.

3.1. A Simple Example

The following code defines a simple class called ethiopia that contains three
data members value1, value2 and value3, together with a single member
function print_values() that prints out the values of all three data members.
The three data members are of data type p, which is the type template parameter
of the class. You can see that the syntax for defining a class template is similar to
that for a function template: the initial line template<class p> indicates that
the following code will define a template using the type template parameter p.
However, note how objects of the templated class are declared in the main
function: the data type required must be written in angled brackets (<, >) after the
class name (e.g. ethiopia<int>).

”class_template.cpp”

#include <iostream.h>

//template class definition


template<class p>
class ethiopia {
public:
//data members
p value1;
p value2;
p value3;

//member functions
void print_values () const {
cout << "Value 1 = " << value1 << endl;
cout << "Value 2 = " << value2 << endl;
cout << "Value 3 = " << value3 << endl;
}
};
6

main () {
//declare integer class object
ethiopia<int> x;
x.value1 = 3;
x.value2 = 5;
x.value3 = 2;
cout << "Integer object\n";
x.print_values();
//declare double class object
ethiopia<double> y;
y.value1 = 123.321;
y.value2 = -43.99;
y.value3 = 0.001;
cout << "Double object\n";
y.print_values();
}

3.2. Templated Array Example

The second example we will consider to illustrate class templates is an array class.
This class allows the programmer to instantiate new arrays using any data type,
and also any length. Therefore this time the class template defined in the “array.h”
file below has two parameters. The type template parameter type has a similar
use to the previous examples we have seen: it indicates the type of the elements in
the array. But this time we also have a value template parameter for the class,
which specifies the number of elements to be included in the array data type. In
fact for any template definition (function template or class template) there are two
types of parameter: type template parameters and value template parameters. As
the names suggest, these let you supply types and values respectively for the
templated function or class.

The TemplateArray class defined in “array.h” uses two constructors. The


default constructor creates the array of length n and data type element. To use
the second constructor the programmer must supply an argument of type
element when declaring the object – this value will be used to initialise the
elements of the array. An example of a declaration that uses this constructor is
given in the second line of the main function.
TemplateArray<int, 8> a(0);
This statement will declare an array of 8 integers and initialise all elements to 0.

The TemplateArray class also provides a function to overload the subscript


operator []. This means that values in the array class can be accessed using
square brackets, just like a normal array in C++.

Again, read through the code below carefully and make sure you understand it.
7

Question 2: Is the following program valid? If not, why not?

#include “array.h”
int main () {
TemplateArray<float, 5> x;
TemplateArray<float, 6> y(0);
x = y;
}

(see the end of this handout for the answer)

”array_test.cpp”

#include <iostream.h>
#include "array.h"
int main () {
//declare a list of 8 integers, initialised to 0
TemplateArray<int, 8> a(0);
a[0] = 1;
a[1] = 3;
a[10] = 4; //index out of range
cout << a[1] << endl;
cout << a[0] << endl;
for (int i = 0; i < 8; i++)
cout << a[i] << " ";
cout << endl;
}

”array.h”

template <class element, int n> class TemplateArray {


// member functions
public:
TemplateArray (); //default constructor
//constructor that initialises all values to 'val'
TemplateArray (element val);
element& operator[] (int); //overload the [] operator
// data members
private:
int size; // number of elements in array
element *array; // the elements
};

template <class element, int n>


TemplateArray<element, n>::TemplateArray () {
size = n;
array = new element[size];
}
8

template <class element, int n>


TemplateArray<element, n>::TemplateArray (element val) {
size = n;
array = new element[size];
for (int i = 0; i < size; i++)
array[i] = val;
}

template <class element, int n>


element& TemplateArray<element, n>::operator[] (int a) {
if ((a >= size) || (a < 0)) {
cout << "Array index out of range" << endl;
return array[0];
}
else
return array[a];
}

4. Templates and Polymorphism

In Handout 2 (Inheritance) the concept of polymorphism in object-oriented


programming was introduced. To recap, the word ‘polymorphism’ refers to a single
object taking a number of different forms. We introduced virtual functions as one way
in which polymorphism is implemented in C++. Templates are the second way. A
templated function or class is a single entity in the program, but it can take on a
number of different forms for different data types.

However, many people do not consider templates to be true polymorphism. The


reason for this is that the choice of which form of the function or class to use is made
at compile-time rather than run-time. That is, templates do not use dynamic binding.
True polymorphism uses dynamic binding. Templates can therefore be described as a
syntactic mechanism that looks like polymorphism to the programmer.

5. Answers to Exercises

Question 1: The templated function used the comparison operator > and the
assignment operator =. Therefore the functions can be used with any data type for
which these two operators are defined. This is true of all of the simple data types in
C++ (e.g. int, char, float, etc.)

Question 2: The code is not valid and would cause a compilation error. The reason for
this is that the two TemplateArray declaration statements declare different types
of array: one is an array of 5 float values and the other is an array of 6 float
values. The assignment operator is only defined for arrays that have exactly the same
type and number of elements.
9

Summary of Key Points

• There are two types of template: function templates and class templates.
• A templated function/class can have a number of different forms
(implementations) that work for different data types.
• Templates can take two different types of parameter: type template
parameters and value template parameters.
• Templates can take multiple parameters of either type.
• Templates can be a useful way to simplify your code. You should use a
template when you want to define a number of functions or classes that are
almost identical, except with regard to the data types they use.

Note: The full source code listings for the examples in this handout can be found on the
FBE network server: to access them, open My Network Places, double-click on
MU-FBE, then FBE-SERVER and then browse to:
Courses\ICT122 – Object-Oriented Programming\src\Handout 4

Notes prepared by: FBE Computer Science Department.


10

Das könnte Ihnen auch gefallen