(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Visual C++: Мыслим шаблонно

Источник: mycomp

Новичку, осваивающему какой-либо язык программирования, то и дело попадаются такие понятия как «процедурное программирование», «модульное программирование», «объектно-ориентированное программирование»; постепенно он начинает проникать в их суть. Термин «обобщенное программирование» куда более редок. Что же это такое, какие возможности оно нам предоставляет? Попробуем ответить на этот вопрос.

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

template<class T> class Имя_класса {/* Тело класса */};
 
Префикс template<class T> указывает, что объявлен шаблон и что аргумент Т будет использован в объявлении как тип. Обратите внимание, что Т - не обязательно имя класса, он может быть любым типом данных. Имя шаблона класса, за которым следует тип, помещенный в угловые скобки, является именем класса, и его можно использовать так же, как и имена других классов. Объект данного класса создается следующим образом:

Имя_класса<Тип> Имя_переменной;
 
Члены шаблона класса объявляются и определяются точно также, как и для обычного класса. Если в шаблоне необходимо параметризировать несколько типов, то их нужно перечислить через запятую в угловых скобках, например, template<class T, class C>.

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

template<class T> Тип_результата Имя_функции(Типы_аргументов)
{
  /* Тело функции */
}
 
Аргумент Т может использоваться как для объявления локальных переменных, так и для определения типов аргументов и типа результата. Вызов шаблона функции происходит так же, как и вызов обычных функций, только после имени функции в угловых скобках необходимо указать тип. Если возможно вывести тип аргумента шаблона функции по типам аргументов при ее вызове, то скобки можно опустить.

Ну что ж, перейдем от теории к практике. Все мы часто используем при написании программ массивы. Бывают случаи, когда размер массива заранее неизвестен. Поэтому приходится выделять под него максимально необходимый объем памяти, что приводит к неэффективному ее использованию. Напишем шаблон класса, который будет объектной реализацией одномерного массива, но, в отличие от простого массива, его размер можно будет увеличивать. Запускаем Microsoft Visual C++ 6.0 и создаем новый проект. Для этого выбираем меню File > New. В диалоговом окне New на закладке Projects в списке типов проекта выбираем Win32 Console Application ( рис. 1). Также указываем имя и размещение проекта. Пусть наш проект будет иметь название masiv. Нажимаем OK и в следующем диалоговом окне выбираем переключатель A simple application ( рис. 2). После этого нажимаем Finish и ждем, пока мастер закончит создание нового проекта. После этого открываем файл masiv.cpp и заменяем его содержимое следующим кодом:

#include "stdafx.h"
#include <iostream.h>
template<class T>class Array
{
  int n;  //Количество элементов массива
  T* a;  //Внутренняя реализация массива
public:
  Array() 
  {
    n=5;   
    a=new T[n];
    for(int i=0; i<n; i++)
      a[i]=0;
  }
  Array(int n1)
  {
    n=index;
    a=new T[n];
    for(int i=0; i<n; i++)
      a[i]=0;
  }
  Array(const Array& mas)
  {
    n=mas.n;
    a=new T[n];
    for(int i=0; i<n; i++)
      a[i]=mas.a[i];
  }
  ~Array()
  {
    delete[] a; 
  }
  //Перегружаем оператор присваивания
  Array& operator=(const Array& mas)
  {
    if (this!=&mas)
    {
      delete[] a;
      n=mas.n;
      a=new T[n];
      for(int i=0; i<n; i++)
        a[i]=mas.a[i];
    }
    return *this;
  }
  //Возвращаем значение элемента массива по заданному индексу
  T& operator[](int index){return a[index];}
  //Возвращаем количество элементов массива
  int length(){return n;}
  //Увеличиваем размер массива на значение col
  void resize(unsigned int col)
  {
    T* tmp = new T[n+col];
    for(int i=0; i<n; i++)
      tmp[i]=a[i];
    delete[] a;
    n+=col;
    a=tmp;
  }
};
int main(int argc, char* argv[])
{
  //Тестируем наш класс
  Array<int> m;
  m[0]=5;
  Array<double> m1;
  m1[0]=2.7+3.3;
  m1[1]=1.5+m1[0]*2;
  m1[3]=m1[0]+m1[1];
  cout<<m[0]<<endl;
  cout<<m1[0]<<endl;
  cout<<m1[1]<<endl;
  cout<<m1[3]<<endl;
  cout<<m1.length()<<endl;
  m1.resize(2);
  cout<<m1.length()<<endl;
  return 0;
}

     


В шаблоне класса Array мы описали все виды конструкторов и деструктор. Также перегрузили операторы присваивания и индекса с помощью функций operator= и operator[]. Обратите внимание, что результатом функции operator[] является ссылка на элемент массива. Это сделано затем, чтобы можно было как получить значение элемента массива, так и присвоить ему какое-то значение. Размер массива можно только увеличить. Для этого аргумент функции resize имеет тип unsigned int. Так как наш шаблон класса имеет небольшой размер, реализации всех функций описаны внутри шаблона. Но функции можно реализовать и вне класса. Например, реализация функции length вне шаблона класса будет выглядеть так:

template<class T> int Array<T>::length()
{
  return n;
}
 
Как видите, тип Т используется в шаблоне класса наравне с другими типами данных. В процессе компиляции будет сгенерирован класс или классы, где Т будет заменен компилятором на конкретный тип. Версия шаблона для конкретного аргумента шаблона называется специализацией, а сам процесс генерации - инстанцированием шаблона. Таким образом, вся черновая робота по написанию специализированного кода будет возложена на компилятор. Теперь наш массив вполне пригоден для использования при написании других программ. При необходимости можно будет расширить его функциональность. Осталось только протестировать наш шаблон. Нажимаем Ctrl+F5 и смотрим результаты теста, код которого описан в функции main ( рис. 3).



 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 29.11.2006 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft Office 365 Бизнес. Подписка на 1 рабочее место на 1 год
Microsoft Office 365 Профессиональный Плюс. Подписка на 1 рабочее место на 1 год
Microsoft Office для дома и учебы 2019 (лицензия ESD)
Microsoft 365 Business Basic (corporate)
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год.
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Компьютерные книги. Рецензии и отзывы
Мастерская программиста
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100