КИТ и Э КБГУ Вторник, 07.05.2024, 05:22
Приветствую Вас Гость | RSS
Меню сайта

Наш опрос
Оцените мой сайт
Всего ответов: 118

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Шаблоны классов. Определение шаблона класса. Функции-члены шаблонов классов. Объявления друзей в шаблонах классов

1. Определение шаблона класса

Класс, который абстрагируется от типа хотя бы одного своего атрибута или от типа параметра хотя бы одного своего метода, называется родовым или обобщенным классом. В языке программирования С++ родовые классы определяются шаблонами классов.

Определение шаблона класса имеет следующий вид:

template <список_параметров>

где в угловых скобках указан список параметров шаблона класса, который не может быть пустым.

Функции-члены шаблона класса могут быть определены как в шаблоне класса, так и вне шаблона класса. В последнем случае они должны быть явно объявлены как члены шаблона класса.

Для шаблонов классов поддерживаются те же модели компиляции, что и для шаблонов функций, а именно, модели компиляции с включением и разделением.

Пример 1. Создадим шаблон класса массив.

У массива должен быть тип, его тип соответствует типу данных, которые он хранит в себе. Внутри массива определенное число данных, поэтому должен быть счетчик элементов. Ничто не мешает создать простой класс Массив, который будет выполнять простые действия: Добавление и Отображение элементов.

#include <stdlib.h>

#include <iostream>

using namespace std;

НАШ КЛАСС*/

class Massiv

 

   int Array[10];                        //Массив целочисленных значений из 10 элементов

   int count;                               //Счетчик элементов массива

   public:

    void Add(int );                     //Метод для добавления элементов в массив

    void Show();                        //Метод для отображения массива на экране

 

/*ДОБАВЛЯЕМ ЭЛЕМЕНТ В МАССИВ*/

void Massiv::Add(int x)

 

   static int pos=0;           //Статическая переменная действует как глобальная, но доступна только там, где живет

   Array[pos]=x;              //Присваиваем принимаемый методом параметр в массив

   pos++;                         //Меняем позицию для следующего присвоения

   count=pos;                   //Счетчик равен последней позиции

 

/*ОТОБРАЖАЕМ МАССИВ НА ЭКРАНЕ*/

void Massiv::Show()

  for ( int i=0;i<count;i++) cout<<Array[i]<<"\t";

//С помощью цикла проходим по всему массиву

  cout<<endl;

int main()

  Massiv Arr;                                     //Объявляем Объект Arr нашего класса Massiv

  Arr.Add(10.555);

  Arr.Add(100);                        //Добавляем элементы

  Arr.Add(300);

  Arr.Show();

return 0;

Это пример создания обычного класса. Но у программистов иногда возникает необходимость создания такого же класса, в котором отличается только тип данных. Например, может потребоваться создание класса, в котором требуется создание массива, который будет хранить в себе и обрабатывать не целочисленные переменные, а строковые. Как вариант, можно дописать кучу классов для каждого из типов переменных, но это не дело. Уйдет некоторое время и код получится большим, громоздким. Чем больше кода, тем проще в нем ошибаться и тем сложнее искать ошибки. Вот тут и приходят на помощь шаблоны классов.

#include <stdlib.h>

#include <iostream>

namespace std;

pos=0;                       //Позиция внутри массива, я решил объявить глобально

<class T>                   //Шаблон с класса с параметром T

Massiv                       //Наш класс

Array[10];                   //Пусть тип массива будет соответствовать типу параметра из Шаблона

 int count;                 //Счетчик элементов

   public:

   void Add(T );               //Метод с параметром-ссылкой на переменную типа параметра из Шаблона

    void Show();               //Метод для отображения массива на экране

template<class T> void Massiv<T>::Add(T x) //Прописываем метод вне класса с использованием шаблона класса

Array[pos]=x;

//Присваиваем в текущий элемент параметр принимаемый методом. Тип этого параметра соответствует типу, принимаемому шаблоном

   pos++;                         //Переходим к позиции следующего элемента

   count=pos;                            //Счетчик равен текущей позиции элемента

template <class T> void Massiv<T>::Show()

//Прописываем метод вне класса с использованием шаблона класса

  for (int i=0;i<count;i++) cout<<Array[i]<<"\t";

//С помощью цикла выводим все данные массива на экран

  cout<<endl;

  pos=0; //После вывода данных обозначаем, что текущий элемент нулевой

int main()

    setlocale(LC_ALL,"");

  Massiv<int> Arr;

//Объявляем переменную типа нашего класса и указываем необходимый для обработки тип в угловых скобках

  Arr.Add(100);                                 //Добавляем элементы

  Arr.Add(200);

  Arr.Add(300);

  Arr.Show();                                     //Отображаем массив на экране

  Massiv<char *> Arr2;

//Объявляем другую переменную типа нашего класса и указываем необходимый для обработки тип в угловых скобках

  Arr2.Add("Строка");                     //Добавляем данные

  Arr2.Add("Начинаю понимать");

  Arr2.Show();

2. Конкретизация шаблона класса

Процесс создания определения класса из шаблона класса называется конкретизацией или инстанциированием шаблона класса. Класс, созданный из шаблона, называется специализацией шаблона класса или шаблонным классом. Шаблон класса конкретизируется только явно.

Шаблон класса конкретизируется только при определении объекта класса. При объявлении ссылок и указателей на класс шаблон класса не конкретизируется, так как в этом случае объект класса может и не существовать. По определению считается, что функция-член шаблона класса сама является шаблоном. Стандарт языка программирования С++ требует, чтобы она конкретизировалась только при вызове или при взятии её адреса. Поэтому при конкретизации шаблона класса компилятор генерирует код только тех функций-членов класса, которые явно или неявно вызываются в программе.

 

Основные свойства шаблонов классов

  • Компонентные функции параметризованного класса автоматически являются параметризованными. Их не обязательно объявлять как параметризованные с помощью template.
  • Дружественные функции, которые описываются в параметризованном классе, не являются автоматически параметризованными функциями, т.е. по умолчанию такие функции являются дружественными для всех классов, которые организуются по данному шаблону.
  • Если friend-функция содержит в своем описании параметр типа параметризованного класса, то для каждого созданного по данному шаблону класса имеется собственная friend-функция.
  • В рамках параметризованного класса нельзя определить friend-шаблоны (дружественные параметризованные классы).
  • С одной стороны, шаблоны могут быть производными (наследоваться) как от шаблонов, так и от обычных классов, с другой стороны, они могут использоваться в качестве базовых для других шаблонов или классов.
  • Шаблоны функций, которые являются членами классов, нельзя описывать как virtual.
  • Локальные классы не могут содержать шаблоны в качестве своих элементов.

 

Реализация компонентной функции шаблона класса, которая находится вне определения шаблона класса, должна включать дополнительно следующие два элемента:

  • Определение должно начинаться с ключевого слова template, за которым следует такой же список_параметров_типов в угловых скобках, какой указан в определении шаблона класса.
  • За именем_класса, предшествующим операции области видимости (::), должен следовать список_имен_параметров шаблона.

template<список_типов>

тип_возвр_значения имя_класса<список_имен_параметров>::имя_функции (список_параметров)

{ ... }

 

Вход на сайт

Поиск

Календарь
«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031

Архив записей

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Copyright Fatima_Zh © 2024Бесплатный хостинг uCoz