Организация исходного кода

T x, y;

T x, y;

};

1) Здесь префикс template <class Т> указывает, что объявлен шаблон класса, в котором Т — некоторый абстрактный тип.

2)То есть ключевое слово class в этом контексте задает вовсе не класс, а означает лишь то, что Т — это параметр шаблона. Вместо Т может использоваться любое имя.

3) После объявления Т используется внутри шаблона точно так же, как имена других типов. Отметим, что язык позволяет вместо ключевого слова class перед параметром шаблона использовать другое ключевое слово — typename, то есть написать:

template < typename Т> class point { /*... */ };

В литературе встречаются оба стиля объявления, но первый, пожалуй, более распространен.

4) Определение встроенных методов внутри шаблона класса практически не отличается от записи в обычном классе. Но если определение метода выносится за пределы шаблона класса, то синтаксис его заголовка усложняется.

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

template <описание_параметров_шаблона>

возвр_тип имя_класса <параметры_шаблона>::

имя_функции (список_параметров функции)

Покажем это на примере

метода Show():

/ / Версия с внешним определением метода ShowO

template <class Т> class point {

public:

point(T _x = 0, T _y = 0): x(_x), y(_y) {}

void Show();

private:

};

template <class T> void point<T>::Show() {

cout << " (" << x << ", " <<у << ")" <<endl;

Обратите внимание на появление того же префикса template <class Т>, который предварял объявление шаблона класса, а также на более сложную запись операции квалификации области видимости для имени Show(): если раньше мы писали point::, то теперь пишем point<T>::, добавляя к имени класса список параметров шаблона, заключенный в угловые скобки (в данном случае один параметр Т)

Использование шаблона класса

При включении шаблона класса в программу никакие классы на самом деле не генерируются до тех пор, пока не будет создан экземпляр шаблонного класса, в котором вместо абстрактного типа Т указывается некоторый конкретный тип.

Такая подстановка приводит к актуализации, или инстанцированию, шаблона. Как и для обычного класса, экземпляр создается либо объявлением объекта, например:

point<int> anyPoint(13, -5);

либо объявлением указателя на актуализированный шаблонный тип с присваиванием ему адреса, возвращаемого операцией new, например:

point<double>* pOtherPoint = new point<double>(9.99. 3.33);

Встретив подобные объявления, компилятор генерирует код соответствующего класса.

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

В связи с этим принято размещать все определения шаблонного класса в некотором заголовочном файле, например point.h, и подключать его к нужным файлам с помощью директивы #include. Для предотвращения повторного включения этого файла, которое может иметь место в многофайловом проекте, обязательно используйте «стражи включения», реализуемые посредством директивы #ifndef

Продемонстрируем эту технику на примере нашего класса point:

/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

/ / point.h

#ifndef POINT_H

#define POINT_H

template <class T> class point {

public:

point(T _х = 0, Т _у = 0): х(_х), у(_у) {}

void Show();

private:

Т x, у;

};

template <class Т> void point<T>::Show() {

cout << " (" << x << ", " << у << ")" << endl;

}

#endif /* POINT_H */

/////////////////////////////////////////////////

// Main.cpp

#include <iostream>

#include "point.h"

using namespace std;

int main() {

point<double> p1; //1

point<double> p2(7.32, -2.6); // 2


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: