'

Шаблоны в С++

Понравилась презентация – покажи это...





Слайд 0

Шаблоны в С++ Макаревич Л. Г.


Слайд 1

Шаблоны функций Многие алгоритмы не зависят от типов данных. #include <iostream> using namespace std; void swap (int& a, int & b) { int t = a; a = b; b = t; } void swap (double& a, double & b) { double t = a; a = b; b = t; } void swap (char& a, char& b) { char t = a; a = b; b = t; } int main() { int i = 5, j = 6; double d = 8.6789, b = 6.7894; char c1='a', c2 = 'f'; swap (i, j); swap (d, b); swap (c1, c2); }


Слайд 2

template < class T> void swap_templ (T& a, T & b) { T t = a; a = b; b = t; } int main() { int i = 5, j = 6; double d = 8.6789, b = 6.7894; char c1='a', c2 = 'f'; swap_templ(i,j); swap_templ(d,b); swap_templ(c1,c2); } template < class A, class B, class C> void f( ) { …} template < class T> void f( T& a, int k) { a = a + k; } int main() { int i = 5; f ( i, 99 ); //можно f<double>(i,99); //будет выполнено преобразование в //double return 0; }


Слайд 3

template <class T> const T& min(const T& a, const T& b) { if (a < b) return a; else return b; } Данная запись еще не создала ни одной функции, это лишь шаблон для определенной функции. Только тогда, когда происходит обращение к функции с аргументами конкретного типа, будет выполнена генерация конкретной функции. int x, y, z; String s1, s2, s3; . . . // генерация функции min для класса String s1 = min(s2, s3); . . . // генерация функции min для типа int x = min(y, z); double d; x = min(y,d);// сообщение об ошибке Первое обращение к функции min генерирует функцию const String& min(const String& a, const String& b); Второе обращение генерирует функцию const int& min(const int& a, const int& b);


Слайд 4

Explicit specification of the template arguments for a function template is allowed. For example: // function_templates2.cpp template<class T> void f(T) { } int myfunction(char j) { f<int>(j); //generate the specialization f(int) } When the template argument is explicitly specified, normal implicit conversions are done to convert the function argument to the type of the corresponding function template parameters. In the above example, the compiler will convert (char j) to type int. Явное указание аргумента шаблона при вызове template<class T> void f(T k) {cout << k; } int myfunction(char j) { f<int>(j); return 5; } int main() { myfunction ('a'); //97 печатается return 0; }


Слайд 5

template < class T> void f(int c , int k) { T& a; a = a + k + c; } int main() { int i = 5; f ( i, 99 ); // ошибка return 0; } В списке параметров шаблона должны быть только классы, входящие в число входных аргументов функции Тип возвращаемого значения может входить в список параметров шаблона, если такой тип есть во входных аргументах функции template < class T> T f(int c , int k) { T a = 0; a = a + k + c; return a; } int main() { int i = 5; int k = f ( i, 99 );// ошибка return 0; }


Слайд 6

#include <iostream> using namespace std; template < class T > void sort(T * a, int n)// сортировка выбором { T t; for ( int i = 0; i < n -1; i++ ) { int imin = i; for ( int j = i + 1; j < n; j++) if ( a[j] < a[imin]) imin = j; t = a[i]; a[i] = a[imin]; a[imin] = t; } } int main() { const int n = 5; int b[n]; for ( int i = 0; i< n; i++ ) cin >> b[i]; sort(b,n); double d[] = {22, 5, 67, 4}; sort(d,4); return 0; }


Слайд 7

Специализированные шаблоны template < class T > void sort(T * a, int n) { T t; for ( int i = 0; i < n -1; i++ ) { int imin = i; for ( int j = i + 1; j < n; j++) if ( a[j] < a[imin]) imin = j; t = a[i]; a[i] = a[imin]; a[imin] = t; } } void sort<>(int * a, int n) { cout << "Not sorted\n"; } int main() { const int n = 5; int b[n]; for ( int i = 0; i< n; i++ ) cin >> b[i]; sort(b,n); double d[] = {22, 5, 67, 4}; sort(d,4); return 0; }


Слайд 8

With a function template, you can define special behavior for a specific type by providing a explicit specialization (override) of the function template for that type. Visual C++ 5.0 and later supports the new syntax for declaring explicit specializations of function templates. For example: // explicit_specialization.cpp template<class T> void f(T t) { }; // Explicit specialization of f with 'char' with the // template argument explicitly specified: template<> void f<char>(char c) { } // Explicit specialization of f with 'double' with the // template argument deduced: template<> void f(double d) { } int main() { } The following form of old syntax is also supported: // Explicit specialization of f with 'char' with the // template argument deduced: // void f(char) {...} Дополнительные возможности задания специализированных шаблонов


Слайд 9

Шаблоны классов Представьте контейнерный класс ( список, очередь, дерево, стек, …) Контейнерный класс предназначен для хранения данных


Слайд 10

class List { class Elem { public: int data; Elem * next; Elem * prev; Elem(){data = 0; next = prev = NULL;} Elem( int d):data(d){next = prev = NULL;} }; Elem * first; Elem * last; public: List(void) { first = last = NULL; } ~List(void) { Elem * pt = first; while ( pt ) { Elem * t = pt; pt = pt->next; delete t; } } Elem * insert( int key, int d)// вставка после узла с ключом key { if (Elem * pkey = find(key)) { Elem * pt = new Elem(d); pt->next = pkey->next; pt->prev = pkey; pkey->next = pt; if ( pkey != last ) (pt->next)->prev = pt; else last = pt; return pt; } return 0; }


Слайд 11

void Add( int d)// вставка в конец списка { Elem * t = new Elem(d); if ( first == NULL ) { first = last = t; } else { t->prev = last; last->next = t; last = t; } } void print() { Elem * pt = first; while ( pt ) { cout << pt->data << '\n'; pt = pt->next; } } void print_reverse() { Elem * pt = last; while ( pt ) { cout << pt->data << '\n'; pt = pt->prev; } } Elem * find ( int d ) { Elem * pt = first; while ( pt ) { if ( pt->data == d ) return pt; pt = pt->next; } return NULL; }


Слайд 12

bool remove( int key ) { if (Elem * pkey = find(key)) { if ( pkey == first ) { first = first->next; first->prev = NULL; } else { if ( pkey == last ) { last = last ->prev; last->next = NULL; } else { (pkey->prev)->next = pkey->next; (pkey->next)->prev = pkey->prev; } } delete pkey; return true; } return false; } }; int main() { List l; for ( int i = 1; i < 25; i++ ) l.Add(i); l.print(); l.print_reverse(); l.insert(1,99); if ( !l.remove(6)) cout << "Not founf!\n"; l.print(); l.print_reverse(); return 0; }


Слайд 13

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


Слайд 14

template < class T> class List { class Elem { public: T data; Elem * next; Elem * prev; Elem(){data = 0; next = prev = NULL;} Elem( T d):data(d){next = prev = NULL;} }; Elem * first; Elem * last; public: List(void) { first = last = NULL; } ~List(void) { Elem * pt = first; while ( pt ) { Elem * t = pt; pt = pt->next; delete t; } } Elem * insert( T key, T d)// вставка после узла с ключом //key { if (Elem * pkey = find(key)) { Elem * pt = new Elem(d); pt->next = pkey->next; pt->prev = pkey; pkey->next = pt; if ( pkey != last ) (pt->next)->prev = pt; else last = pt; return pt; } return 0; }


Слайд 15

void Add( T d)// вставка в конец списка { Elem * t = new Elem(d); if ( first == NULL ) { first = last = t; } else { t->prev = last; last->next = t; last = t; } } void print() { Elem * pt = first; while ( pt ) { cout << pt->data << '\n'; pt = pt->next; } } void print_reverse() { Elem * pt = last; while ( pt ) { cout << pt->data << '\n'; pt = pt->prev; } } Elem * find ( T d ) { Elem * pt = first; while ( pt ) { if ( pt->data == d ) return pt; pt = pt->next; } return NULL; }


Слайд 16

bool remove(T key ) { if (Elem * pkey = find(key)) { if ( pkey == first ) { first = first->next; first->prev = NULL; } else { if ( pkey == last ) { last = last ->prev; last->next = NULL; } else { (pkey->prev)->next = pkey->next; (pkey->next)->prev = pkey->prev; } } delete pkey; return true; } return false; } }; int main() { List < int> l; for ( int i = 1; i < 5; i++ ) l.Add(i); l.print(); l.print_reverse(); l.insert(1,99); if ( !l.remove(4)) cout << "Not found!\n"; l.print(); l.print_reverse(); List < char> lch; for ( int i = 0; i < 5; i++ ) lch.Add('a'+i); lch.print(); lch.print_reverse(); lch.insert('a','z'); if ( !lch.remove('a')) cout << "Not found!\n"; lch.print(); lch.print_reverse(); return 0; }


Слайд 17

Использование итераторов #define NULL 0 #include <iostream> using namespace std; template <class T> class List { class Elem { public: T data; Elem * next; Elem * prev; public: Elem(){data = 0; next = prev = NULL;} Elem( T d):data(d){next = prev = NULL;} }; Elem * first; Elem * last; public: List(void) { first = last = NULL; } ~List(void) { Elem * pt = first; while ( pt ) { Elem * t = pt; pt = pt->next; delete t; } } void Add( T d)// вставка в конец списка { Elem * t = new Elem(d); if ( first == NULL ) { first = last = t; } else { t->prev = last; last->next = t; last = t; } } void print() { Elem * pt = first; while ( pt ) { cout << pt->data << '\n'; pt = pt->next; } } public: class Iterator { List * p; Elem * tek; public: Iterator(List *_p):p(_p){tek = p->first;} T gettek(){return tek->data;} bool next() { if ( tek == NULL ) return false; tek = tek->next; if ( tek != NULL) return true; return false; } void setfirst(){ tek = p->first;} }; }; void main() { List <int> qq; for ( int i = 0; i < 10; i++) qq.Add(i); List<int>::Iterator it(&qq); for ( i = 0; i < 5; i++) { cout << it.gettek()<< '\n'; it.next(); } }


Слайд 18

You can use class templates to create a family of classes that operate on a type. // class_templates.cpp template <class T, int i> class TempClass { public: TempClass( void ); ~TempClass( void ); int MemberSet( T a, int b ); private: T Tarray[i]; int arraysize; }; int main() { TempClass < char, 88> ma; } In this example, the templated class uses two parameters, a type T and an int i. The T parameter can be passed any type, including structures and classes. The i parameter has to be passed an integer constant. Because i is a constant defined at compile time, you can define a member array of size i using a standard array declaration.


Слайд 19

Члены шаблонов template <class T, int i> class TempClass { int MemberSet(T, int); }; template <class T, int i> int TempClass< T, i >::MemberSet( T a, int b ) { if( ( b >= 0 ) && (b < i) ) { Tarray[b++] = a; return sizeof( a ); } else return -1; } template <список параметров шаблона> тип_возврата имя_класса < параметры шаблона> :: имя_функции ( список параметров функции) { // тело функции }


Слайд 20

В шаблоне можно использовать шаблонные функции, но функция должна быть описана в шаблоне. template<typename T> class X { public: template<typename U> void mf(const U &u) { } }; int main() { } Так нельзя: template<typename T> class X { public: template<typename U> void mf(const U &u); }; template<typename T> template <typename U> void X<T>::mf(const U &u) { } int main() { }


Слайд 21

Конструкторы и деструкторы в шаблонах template <class T, int i> class TempClass { TempClass(); ~TempClass(); }; template <class T, int i> TempClass< T, i >::TempClass( void ) { TRACE( "TempClass created.\n" ); } template <class T, int i> TempClass< T, i >::~TempClass( void ) { TRACE( "TempClass destroyed.\n" ); } int main() { }


Слайд 22

template<class T, int i> class MyStack { T* pStack; T StackBuffer[i]; static const int cItems = i * sizeof(T); public: MyStack( void ); void push( const T item ); T& pop( void ); }; template< class T, int i > MyStack< T, i >::MyStack( void ) { }; template< class T, int i > void MyStack< T, i >::push( const T item ) { }; template< class T, int i > T& MyStack< T, i >::pop( void ) { }; int main() { }


Слайд 23

template<class T, int i = 50> class MyStack { T* pStack; T StackBuffer[i]; public: static const int cItems = i * sizeof(T); MyStack( void ); void push( const T item ); T pop( void ); }; template< class T, int i > MyStack< T, i >::MyStack( void ) { pStack = &StackBuffer[0]; }; template< class T, int i > void MyStack< T, i >::push( const T item ) { *pStack = item; pStack++; }; template< class T, int i > T MyStack< T, i >::pop( void ) { --pStack; return *pStack; }; int main() { MyStack < int, 10> mys; for ( int i = 0; i < 6; i++) mys.push(i); for ( i = 0; i < 6; i++) cout << mys.pop()<< '\n'; cout << mys.cItems;// 40 }


Слайд 24

MyStack< unsigned long, 5 > stack1; // creates a stack of // unsigned longs MyStack< DWORD, 5 > stack2; // uses code created above MyStack< char, 6 > stack3; // generates new code MyStack< MyClass, 6 > stack4; // generates stack of //MyClass objects


Слайд 25

Специализация шаблона класса: Специализация отдельного метода Специализация класса template < class T> void List<T>::print();// общий метод void List<char>::print();// специализированный метод template < class T, int k = 500> class Block { }; class Block <int, 100> { // повторяется все тело класса };


Слайд 26

template <class T = char > class MyString { }; MyString <int> ms; MyString <> ms_char; template <class T > class My { int x; }; template <class T > class My <T *>// специализация шаблона { long x; }; template <template <class U > class V> class C // параметр шаблона – // шаблон со специализацией { V <int> y; V< int *> z; }; C < A> c;


Слайд 27

Использование параметра шаблона и параметра конструктора template<class T, int i = 50> class MyStack { T* pStack; int tek; public: MyStack( void ){tek = 0; pStack = new T[i];} void push( const T item ){pStack[tek++]=item;} T pop( void ){return pStack[--i];} }; template<class T> class MyStack { T* pStack; int tek; public: MyStack( int k = 50 ){tek = 0; pStack = new T[k];} void push( const T item ){pStack[tek++]=item;} T pop( void ){return pStack[--i];} };


Слайд 28

template<typename T> class X // или class { public: template<typename U> void mf(const U &u) {U i = u; } }; int main() { X<int> x1; x1.mf( 55); return 0; }


Слайд 29

Правила создания шаблонов Шаблон должен лежать в h-файле Отдавайте предпочтение шаблонам перед производными классами, если важно время выполнения Отдавайте предпочтение производным классам перед шаблонами, если важно добавление нового кода без перекомпиляции Отдавайте предпочтение шаблонам перед производными классами, если нельзя выделить общий базовый класс Шаблоны – полиморфизм времени компиляции или параметрический полиморфизм На шаблонах основаны библиотеки контейнерных классов , например, STL


×

HTML:





Ссылка: