ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4322
Скачиваний: 28
Часть II. Язык программирования С++
256
Не разрешается объявлять шаблонами виртуальные функции-
члены класса. Это обусловлено тем, что возникают проблемы с
построением таблицы виртуальных функций. Так как в этом слу-
чае при обработке определения класса компилятор не может оп-
ределить количество виртуальных функций класса, которые бу-
дут конкретизированы из шаблона функции.
Кроме того, следует отметить, что специализация шаблона не
виртуальной функции-члена класса в производном классе не за-
мещает соответствующую виртуальную функцию-член базового
класса. Это происходит потому, что компилятор добавляет к
имени шаблонной функции типы аргументов, для которых эта
функция специализирована.
В листинге 18.13 показано, что шаблонная функция производного
класса не замещает виртуальную функцию базового класса.
Листинг 18.13. Определение шаблона функции
в производном классе
#include <iostream>
using namespace std;
class Base
{
public:
virtual int foo(const int &n) { return n; }
};
class Derived: public Base
{
public:
template <class T> T foo(const T &t) { return 2*t; }
};
int main()
{
Derived d;
Base* b = &d;
cout << b->foo(10) << endl; // печатает: 10
cout << d.foo(10) << endl; // печатает: 20
return 0;
}
Г Л А В А
19
Шаблоны классов
19.1. Определение шаблона класса
Класс, который абстрагируется от типа хотя бы одного своего
члена, называется
родовым
или
обобщенным
(generic)
классом
.
В языке программирования С++ родовые классы определяются
шаблонами классов
. Определение шаблона класса имеет следую-
щий вид:
template <список_параметров>
определение_класса
В угловых скобках указан список параметров шаблона класса,
который не может быть пустым. Параметры шаблона класса
имеют тот же смысл и подчиняются тем же требованиям, что и
параметры шаблона функции.
Функции-члены шаблона класса могут быть определены как в
шаблоне класса, так и вне его. В последнем случае они должны
быть явно объявлены как члены шаблона класса.
В листинге 19.1 приведен пример шаблона контейнерного клас-
са
Box
, предназначенного для хранения значения определенного
типа
T
, который является параметром шаблона класса. Используя
этот шаблон класса, можно создавать контейнерные объекты для
хранения значений любого типа.
Часть II. Язык программирования С++
258
Листинг 19.1. Определение шаблона класса
Box
template <class T> class Box
{
bool empty; // состояние контейнера
T room; // место для хранения значения
public:
Box(): empty(true) {}
void put(T a); // положить значение в контейнер
T get(); // извлечь значение из контейнера
bool isEmpty() const; // проверить, свободен ли контейнер
};
template <class T> void Box<T>::put(T a)
{
room = a;
empty = false;
}
template <class T> T Box<T>::get()
{
empty = true;
return room;
}
template <class T> bool Box<T>::isEmpty() const
{
return empty;
}
В листинге 19.2 приведен пример шаблона контейнерного класса
Stack
, предназначенного для хранения значений определенного
типа
T
, который является параметром шаблона класса. Размер-
ность стека задается целочисленным параметром
n
шаблона клас-
са. Конечно, параметр для задания размерности стека можно бы-
ло бы определить и в конструкторе класса, а не в списке парамет-
ров шаблона.
Листинг 19.2. Шаблон класса
Stack
template <class T, int n> class Stack
{
int size; // размер стека
Глава 19. Шаблоны классов
259
int top; // верхушка стека
T* a; // указатель на массив
public:
Stack(): size(n), top(0), a(new int[size]) {}
~Stack() { delete[] a; }
void push(const T& n) { a[top++] = n; }
void pop(T& n) { n = a[--top]; }
bool isEmpty() const { return !top; }
bool isFull() const { return top == size; }
};
Параметром шаблона класса может быть также шаблон класса.
Использование шаблонов класса в качестве параметров шаблонов
классов будет рассмотрено в
разд. 19.12
.
Для шаблонов классов поддерживаются те же модели компиля-
ции, что и для шаблонов функций, а именно модели компиляции
с включением и разделением.
19.2. Конкретизация шаблона
класса
Процесс создания определения класса из шаблона класса называ-
ется
конкретизацией
или
инстанциированием
(instantiation)
шаб-
лона класса
. Класс, созданный из шаблона, называется
специали-
зацией шаблона класса
или
шаблонным классом
. Шаблон класса
конкретизируется только явно.
В листинге 19.3 приведены примеры конкретизации шаблона
класса
Box
, определенного в листинге 19.1. Предполагается, что
определение этого шаблона хранится в заголовочном файле
Box.h.
Листинг 19.3. Конкретизация шаблона класса
Box
#include "Box.h"
#include <iostream>
using namespace std;
Часть II. Язык программирования С++
260
int main()
{
// объект для хранения целого числа
Box<int> n;
n.put(10);
cout << n.isEmpty() << endl;
cout << n.get() << endl;
cout << n.isEmpty() << endl;
// объект для хранения числа с плавающей точкой
Box<double> m;
m.put(5.5);
cout << m.isEmpty() << endl;
cout << m.get() << endl;
cout << m.isEmpty() << endl;
return 0;
}
В листинге 19.4 приведен пример конкретизации шаблона класса
Stack
, определенного в листинге 19.2. Предполагается, что опре-
деление этого шаблона хранится в заголовочном файле Stack.h.
Листинг 19.4. Конкретизация шаблона класса
Stack
#include "Stack.h"
#include <iostream>
using namespace std;
int main()
{
int n;
Stack<int, 2> s; // стек для хранения двух целых чисел
cout << s.isEmpty() << ' ' << s.isFull() << endl;
s.push(10);
s.push(20);
cout << s.isEmpty() << ' ' << s.isFull() << endl;
s.pop(n);
cout << n << endl;
s.pop(n);