- •11. Инкапсуляция
- •12. Полиморфизм
- •13. Наследование
- •Управление доступом
- •Элементы класса
- •Элементы данных
- •Элементы функции
- •15. Перегрузка функций
- •16. Конструкторы и деструкторы Конструктор
- •Деструктор
- •17. Параметризированные конструкторы
- •18. Дружественные функции
- •19. Inline-функции
- •20. Передача объектов в функции
- •21. Возвращение объектов функциями
- •22. Массивы объектов
- •23. Указатели на объекты
- •24. Указатель this
- •25. Перегрузка операторов
- •26. Ссылки
- •27. Наследование и спецификаторы доступа
- •28. Конструкторы и деструкторы производных классов
- •29. Множественное наследование. Передача параметров в конструктор базового класса
- •30. Указатели и ссылки на производные типы
- •31. Виртуальные функции
- •32. Чисто виртуальные функции и абстрактные типы
- •33. Раннее и позднее связывание
- •35. Создание собственных операторов вставки и извлечения.
- •36. Форматирование ввода-вывода
- •37. Файловый ввод-вывод
- •38. Чтение и запись в текстовые файлы
- •39. Двоичные файлы
- •40. Функции-шаблоны
- •41. Классы-шаблоны
- •42. Использование пространства имён
- •43. Контейнерные классы
- •46. Основы обработки исключений
- •47. Идентификация типа во время исполнения (rtti)
- •49. Виртуальный базовый класс
41. Классы-шаблоны
Кроме функций – шаблонов можно также определить классы – шаблоны. Для этого следует создать класс, определяющий все алгоритмы, но фактический тип данных является параметром, определяющимся при создании класса.
Общая форма объявления класса – шаблона приведена ниже:
template <class T> class имя_класса {
…
};
Здесь T является параметром – типом, который будет указан при создании объекта класса. При необходимости можно определить несколько типов – шаблонов, используя список и запятую в качестве разделителя.
После создания класса – шаблона можно создать конкретный экземпляр класса и объекты этого класса, использую общую форму:
имя_класса <тип> объект;
Здесь тип является именем типа данных, с которым будет оперировать данный класс.
Функции – члены класса – шаблона являются сами по себе автоматически шаблонами.
В следующей программе создаётся класс – шаблон stack, реализующий стандартный стек «последним вошёл – первым вышел». Он может использоваться для реализации стека с произвольным типом данных.
Листинг 4
// демонстрация класса-шаблона stack
#include <iostream>
using namespace std;
const int SIZE = 100;
// создание класса-шаблона stack
template <class SType> class stack{
SType stck[SIZE];
int tos;
public:
stack();
~stack();
void push(SType i);
SType pop();
};
// функция-конструктор stack
template <class SType> stack<SType>::stack()
{
tos = 0;
cout << "Stack initialized\n";
}
// функция-деструктор stack
template <class SType> stack<SType>::~stack()
{
cout << "Stack destroyed\n";
}
// помещение объекта в стек
template <class SType> void stack<SType>::push(SType i)
{
if(tos==SIZE) {
cout << "Stack is full.\n";
return;
}
stck[tos] = i;
tos++;
}
// извлечение объекта из стека
template <class SType> SType stack<SType>::pop()
{
if(tos==0) {
cout << "Stack underflow.\n";
return 0;
}
tos--;
return stck[tos];
}
int main()
{
stack<int> a;
stack<char> c;
a.push(1);
a.push(2);
cout << a.pop() << " ";
cout << a.pop() << "\n";
register int i;
for(i=0; i<10; i++) c.push((char) 'A'+i);
for(i=0; i<10; i++) cout << c.pop();
cout << "\n";
return 0;
}
Класс-шаблон может иметь несколько типов-шаблонов. Достаточно объявить все типы-шаблоны в виде списка, разделённого запятыми.
// используются два типа-параметра
#include <iostream>
using namespace std;
template <class Type1, class Type2> class Myclass
{
Type1 i;
Type2 j;
public:
Myclass(Type1 a, Type2 b){ i=a; j=b; }
void show(){cout << i << " " << j << "\n";}
};
int main()
{
Myclass<int, double> ob1(10, 0.23);
Myclass<char, char *> ob2('X', "This is a test");
ob1.show();
ob2.show();
return 0;
}
42. Использование пространства имён
Поскольку пространства с глобальной областью видимости добавляются к системе, то имеется возможность коллизии имён. Это становится особенно актуальным при использовании библиотек, разработанных различными независимыми производителями. Использование namespace позволяет разбить глобальное пространство имён для того, чтобы решить проблему.
Общая форма namespace следующая:
namespace имя{
// объявление объекта
}
Пример
namespace MyNameSpace {
int i, k;
void myfunc(int j) {cout << j;}
}
Здесь i, k и myfunc() составляют область видимости пространства имён MyNameSpace.
Поскольку пространство имён определяет область видимости, то для ссылки на объекты, определённые в пространстве имён, необходимо использовать оператор области видимости. Например:
MyNameSpace::i =10;
Если элементы области видимости будут использоваться часто, то можно использовать директиву using для упрощения доступа к ним. Инструкция using имеет две общие формы записи:
using namespace имя;
using имя::член;
В первом случае имя определяет пространство имён, к которому нужно получить доступ. Все члены, определённые в указанном пространстве имён, могут быть использованы без оператора области видимости. Во втором варианте только указанные члены пространства имён становятся видимыми. Например, для определённого выше пространства имен MyNameSpace следующее использование инструкции using является корректным:
using MyNameSpace::k; // видим только k
k = 10; // допустимо, поскольку k видим
using namespace MyNameSpace; // все члены MyNameSpace видимы
i = 10;