- •ШАБЛОНЫ ФУНКЦИЙ И КЛАССОВ
- •Шаблоны функций
- •Все описания шаблонов функций начинаются с ключевого слова template, за котором следует
- •Формальные параметры в описании шаблона используются (наряду с параметрами встроенных типов или типов,
- •Далее, за этим заголовком, следует обычное описание функции.
- •int main() {
- •PrintArray(a,aCount);
- •Шаблоны функций расширяют возможности многократного использования программного кода.
- •Перегрузка шаблонных функций
- •Алгоритм компилятора при работе с перегруженными шаблонами функций:
- •3) если такого шаблона нет, то выводится сообщение об ошибке.
- •PrintArray(a,aCount); //генерируется шаблонная функция void PrintArray(const int* array, const int count) на основе
- •PrintArray(c,cCount); // вызывается нешаблонная функция void PrintArray(char* array, const int count)
- •Шаблоны классов
- •Процесс генерации компилятором определения конкретного класса по шаблону класса и
- •public:
- •Пример. Шаблон класса список
- •void AddElem(type *d); bool RemoveElem(type *d); void DisplayList();
- •else {
- •T p[elements]; int count;
- •Особенности применения наследования
- •1.От каждого класса произвести потомка с перекрытой соответствующей функцией. В этом случае программа
- •class B
- •Пример. Определение класса – потомка шаблонного класса
- •Шаблоны и наследование связаны друг с другом следующим образом:
- •Шаблоны и друзья
- •Шаблоны и статические члены
- •Пример. Статическое поле в шаблоне класса
- •int main() {
Перегрузка шаблонных функций
Компилятор использует механизм перегрузки для того, чтобы обеспечить работу с шаблонами функций.
Шаблон функции можно перегружать:
1)шаблоном функции с другим набором параметров;
2)нешаблонной функцией с указанием точных типов параметров.
Алгоритм компилятора при работе с перегруженными шаблонами функций:
1)компилятор пытается найти и использовать функцию, которая точно соответствует по своему имени и типам параметров вызываемой функции.
2)если такая функция не находится, то компилятор ищет шаблон функции, с помощью которого он может сгенерировать шаблонную функцию с точным соответствием типов параметров и имени функции, и генерирует эту функцию.
3) если такого шаблона нет, то выводится сообщение об ошибке.
Пример. Использование перегруженных шаблонов функций и нешаблонных функций
template <class T>
void PrintArray(const T* array, const int count)
{...}
void PrintArray(char* array, const int count) { for (int i=0; i<count; i++)
cout<<array[i]<<endl;
}
template <class T>
void PrintArray(const T* array, const int lowSubscript, const int highSubscript) {
for (int i=lowSubscript; i<=highSubscript; i++) cout<<array[i]<<" ";
cout<<endl;
}
int main() {
const int aCount=5, bCount=7, cCount=6; int a[aCount]={...};
double b[bCount] = {...}; char c[cCount]="HELLO";
PrintArray(a,aCount); //генерируется шаблонная функция void PrintArray(const int* array, const int count) на основе первого шаблона
PrintArray(b,2,5); //генерируется шаблонная функция PrintArray(const double* array, const int lowSubscript, const int highSubscript) на основе второго шаблона
PrintArray(c,cCount); // вызывается нешаблонная функция void PrintArray(char* array, const int count)
return 0;
}
Замечание. Компилятор ищет шаблон, полностью соответствующий вызываемой функции по типу всех параметров; автоматическое преобразование типов не производится (возможно, char к int, double к int и т.д.).
Шаблоны классов
Шаблоны классов, так же как и шаблоны
функций, поддерживают в C++ парадигму
обобщенного программирования, то есть программирования с использованием типов в качестве параметров.
С помощью шаблона классов удобно работать с контейнерными классами, такими как списки, ассоциативные массивы.
После того как шаблон класса определен, он может использоваться для определения конкретных классов.
Процесс генерации компилятором определения конкретного класса по шаблону класса и
аргументам шаблона называется
инстанцированием шаблона (template instantiation).
Пример. Шаблон класса stack (стек)
template<class T> class stack
{
T* v; T* p; int sz;
public:
stack(int s) { v = p = new T[sz=s]; } ~stack() { delete[] v; }
void push(T a);
T pop() { return *--p; }
int size() const { return p-v; }
};
template<class T> void stack<T>::push(T a) { *p++ = a;
}
typedef struct _Point {
int x,y; }Point;
int main() { stack<Complex> sc(100); stack<Point> sp(400);
sc.push(Complex(1,2)); Complex z=sc.pop(); cout<<z;
stack<int>*p = 0;
p = new stack<int>(800);
for ( int i = 0; i<400; i++) { p->push(i);
Point p1; p1.x=i;
p1.y=i+400; sp.push(p1);
}
cout<<"Размер стеков: "<<sp.size()<<" "<< p- >size()<<endl;
cout<<p->pop()<<endl;
Point p2; p2=sp.pop();
cout<<"X="<<p2.x<<" Y="<<p2.y<<endl; return 0;
}