Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

pragma once Hard / Занятие 6

.doc
Скачиваний:
42
Добавлен:
13.03.2015
Размер:
45.06 Кб
Скачать

Шаблоны функций и классов

Пример 3.1

Создадим функцию-шаблон, которая находит максимальное значение. Применение функции для данных различного типа продемонстрировано в функции main. Функция использует для сравнения данных операцию >.

Так как для строк операция > не определена, для них с помощью перегрузки создана специальная версия функции max. В этой версии функции используется функция strcoll, которая для строк x и y возвращает отрицательное число, если x<y, ноль, если x=y, положительное число, если x>y. При сравнении учитывается регистр и локальные настройки.

Рассматриваемую функцию-шаблон можно использовать и для объектов, если для них определена операция >. В качестве примера рассматривается класс segment (отрезок).

#include <iostream>

using namespace std;

#include <cmath>

#include <cstring>

//функция-шаблон max

template <class T> T max(T &x, T &y) {

if(x>y) return x; else return y;

}

char* max(char *x, char *y) {

if(strcoll(x,y)>0) return x; else return y;

}

//класс segment (отрезок), в котором есть перегруженная операция >

class segment {

public:

double x;

double y;

double length(){ return abs(y-x);}

segment(){x=0; y=1;}

segment(double a, double b){x=a;y=b;}

void show() {cout<<'['<<x<<';'<<y<<']';}

bool operator >(segment &Z){

return length() > Z.length();}

};

int main() {

int i=10, j=20;

cout<<"max = "<<max(i, j)<<endl;

char c1='a', c2='b';

cout<<"max = "<<max(c1,c2)<<endl;

char s1[]="ab001"; char s2[]="ab01";

cout<<"max = "<<max(s1,s2)<<endl;

//используем функцию-шаблон для объектов

segment A(-2, 9), B(25.5, 27.1), C;

A.show(); cout<<endl;

B.show(); cout<<endl;

C=max(A, B);

cout<<"max= "; C.show(); cout<<endl;

}

Пример 3.2

Создадим функцию-шаблон для сортировки массива в порядке возрастания, использующую алгоритм пузырьковой сортировки. Функцию можно использовать для сортировки объектов, если в соответствующем классе реализованы операции < и = (присваивание). В примере показано, как можно использовать эту функцию для сортировки массивов различных типов (int, double, segment). Для класса segment не потребовалось создавать перегруженную операцию присваивания, так как в нем нет динамических объектов. Побитовое копирование, которое при присваивании выполняется по умолчанию, в данном случае работает корректно.

#include <iostream>

using namespace std;

#include <cmath>

//функция-шаблон sort

template <class T> void sort(T *x, int n) {

int i,j; T r;

for (i=0;i<n-1;i++)

for (j=0;j<n-i-1;j++)

if(x[j]>x[j+1]){r=x[j]; x[j]=x[j+1]; x[j+1]=r;}

}

//класс segment (отрезок), в котором есть перегруженная операция >

class segment {

public:

double x;

double y;

double length(){ return abs(y-x);}

segment(){x=0; y=1;}

segment(double a, double b){x=a;y=b;}

void show() {cout<<'['<<x<<';'<<y<<']';}

bool operator >(segment &Z){

return length() > Z.length();}

};

int main() {

int i;

int P[4]={3, 2, 7, -1};

for (i=0; i<4; i++) {cout<<P[i]<<" ";} cout<<endl;

sort(P,4);

for (i=0; i<4; i++) {cout<<P[i]<<" ";} cout<<endl;

double Q[5]={-1.3, 8.2, 0.7, -1, 2.7};

for (i=0; i<5; i++) {cout<<Q[i]<<" ";} cout<<endl;

sort(Q,5);

for (i=0; i<5; i++) {cout<<Q[i]<<" ";} cout<<endl;

segment V[3];

V[0].x=0; V[1].x=-1.5; V[2].x=1.8;

V[0].y=3; V[1].y=5.2; V[2].y=4.3;

for (i=0; i<3; i++) {V[i].show(); cout<<" ";} cout<<endl;

sort(V,3);

for (i=0; i<3; i++) {V[i].show(); cout<<" ";} cout<<endl;

}

Пример 3.3

Создадим шаблонный класс stack, который позволит использовать стеки для хранения объектов различных типов. В функции main создаются 3 стека для хранения целых чисел, символов и указателей на объекты segment.

При объявлении шаблонного метода вне класса используется следующий синтаксис:

template <class Tип1 [,…, class типN]>

ТипРезультата ИмяКласса <Tип1 [,…, типN]>::

ИмяМетода(ПараметрыМетода)

В данном случае Tип1,…, типN – формальные параметры-типы. Для создания объектов с помощью шаблонного класса используется конструкция

ИмяКласса <Tип1 [,…, типN]> ИмяПеременной [(параметры_конструктора)];

При создании объекта внутри угловых скобок указываются реальные типы данных.

#include <iostream>

using namespace std;

template <class T> class stack {

struct Elem{

T d;

Elem *next;

};

Elem *top; // указатель на вершину стека

public:

stack () {top=NULL;}

stack (T x) {top=NULL; put(x);}

~stack ();

void put (T x);

T get();

};

class segment {

public:

double x;

double y;

double length(){ return abs(y-x);}

segment(){x=0; y=1;}

segment(double a, double b){x=a;y=b;}

void show() {cout<<'['<<x<<';'<<y<<']';}

bool operator >(segment &Z){

return length() > Z.length();}

};

template <class T> stack <T>::~stack ()

{

if (top!=NULL) {

Elem *p = top;

while (top){

p = top->next;

delete top;

top=p;

}

}

}

template <class T> void stack <T>::put (T x)

{

Elem *p = new Elem;

p->d = x; p->next = top;

top = p;

}

template <class T> T stack <T>::get()

{

if (top==NULL)

{

cout << " stack is empty";

return 0;

}

else

{

Elem *p = top;

top = top->next;

T d = p->d;

delete p;

return d;

}

}

int main()

{

stack <int> P;

for (int i=1;i<10;i++) P.put(i);

cout<<"P: ";

for (int i=1;i<10;i++) cout<<P.get()<<' ';

cout<<endl;

stack <char> Q;

for (char c='a';c<='z';c++) Q.put(c);

cout<<"Q: ";

while(char c=Q.get()) cout<<c<<' ';

cout<<endl;

segment A(-2, 9), B(25.5, 27.1), C(0.5,7.2);

stack <segment *> R;

R.put(&A); R.put(&B); R.put(&C);

cout<<"R: ";

while(segment *s=R.get()){s->show();cout<<' ';}

cout<<endl;

}

Задания:

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

6

Соседние файлы в папке pragma once Hard