![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Wowa |
|
|||
|
Эксперт Профиль Группа: Админ Сообщений: 15017 Регистрация: 14.9.2000 Где: Винград Репутация: нет Всего: 290 |
Расскажите, пожалуйста, про template
Что это, для чего, и краткий пример использования. |
|||
|
||||
| maxim1000 |
|
||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
пример:
дали переменную, сказали посчитать в ней количество бит, равных 1 спрашиваем, для каких типов реализовать? ответ: char,int,void*,double можно, конечно, написать все 4 функции и не мучаться
но нам хочется сделать все это одной функцией так вот шаблоны этого НЕ позволяют вместо этого шаблоны позволяют научить компилятор генерировать подобные функции, когда будет нужно:
это - просто пишется в исходном или заголовочном файле (подробнее) когда компилятор видит попытку использования одной из таких функций (это все - абсолютно разные функции), он добавляет ее реализацию, соответственно шаблону с нужным типом вместо T:
а как сделать ссылку на конкретное сообщение? Это сообщение отредактировал(а) maxim1000 - 17.2.2005, 14:32 -------------------- qqq |
||||||
|
|||||||
| pablo |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 320 Регистрация: 12.2.2005 Где: Вильнюс, Литва Репутация: 4 Всего: 6 |
template - это ключевое слово С++, означающее использование шаблона.
После слова template в <типы или типовые параметры>, шаблонами могут быть не только функции, но и классы. Как правило используется там, где надо написать алгоритм который будет работать одинакого с разными типами данных. Вот пример использования: // List.h: interface for the List class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_LIST_H__BC404E61_5B68_4FA2_82B5_99EB5C8DBFE5__INCLUDED_) #define AFX_LIST_H__BC404E61_5B68_4FA2_82B5_99EB5C8DBFE5__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <iostream> using std::cout; #include <new> #include "ListNode.h" // ListNode class definition template< typename NODETYPE > class List { public: List(); // constructor ~List(); // destructor void insertAtFront( const NODETYPE & ); void insertAtBack( const NODETYPE & ); bool removeFromFront( NODETYPE & ); bool removeFromBack( NODETYPE & ); bool isEmpty() const; void print() const; List< NODETYPE > & operator = (const List< NODETYPE > &); int operator < (const List< NODETYPE > &); int numberOfElements() const; private: int length; ListNode< NODETYPE > *firstPtr; // pointer to first node // utility function to allocate new node ListNode< NODETYPE > *getNewNode( const NODETYPE & ); }; // end class List // default constructor template< typename NODETYPE > List< NODETYPE >::List(): firstPtr( 0 ), length(0) { // empty body } // end List constructor // destructor template< typename NODETYPE > List< NODETYPE >::~List() { if ( !isEmpty() ) { // List is not empty ListNode< NODETYPE > *currentPtr = firstPtr; ListNode< NODETYPE > *tempPtr; while ( currentPtr != 0 ) { // delete remaining nodes tempPtr = currentPtr; currentPtr = currentPtr->nextPtr; delete tempPtr; } // end while } // end if } // end List destructor // insert node at front of list template< typename NODETYPE > void List< NODETYPE >::insertAtFront( const NODETYPE &value ) { ListNode< NODETYPE > *newPtr = getNewNode( value ); if ( isEmpty() ) // List is empty { firstPtr = newPtr; length++; } else { // List is not empty newPtr->nextPtr = firstPtr; firstPtr = newPtr; length++; } // end else } // end function insertAtFront // insert node at back of list template< typename NODETYPE > void List< NODETYPE >::insertAtBack( const NODETYPE &value ) { ListNode< NODETYPE > *newPtr = getNewNode( value ); if ( isEmpty() ) // List is empty { firstPtr = newPtr; length++; } else { // List is not empty while(firstPtr) { firstPtr = firstPtr->nextPtr; } firstPtr->nextPtr = newPtr; firstPtr = newPtr; length++; } // end else } // end function insertAtBack // delete node from front of list template< typename NODETYPE > bool List< NODETYPE >::removeFromFront( NODETYPE &value ) { if ( isEmpty() ) // List is empty return false; // delete unsuccessful else { ListNode< NODETYPE > *tempPtr = firstPtr; if ( firstPtr == lastPtr ) firstPtr = lastPtr = 0; else firstPtr = firstPtr->nextPtr; value = tempPtr->data; // data being removed delete tempPtr; length--; return true; // delete successful } // end else } // end function removeFromFront // delete node from back of list template< typename NODETYPE > bool List< NODETYPE >::removeFromBack( NODETYPE &value ) { if ( isEmpty() ) return false; // delete unsuccessful else { ListNode< NODETYPE > *tempPtr; if ( firstPtr->nextPtr ) firstPtr = 0; else { ListNode< NODETYPE > *currentPtr = firstPtr; while(firstPtr->nextPtr) { firstPtr = firstPtr->nextPtr; } // locate second-to-last element while ( currentPtr->nextPtr != lastPtr ) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } // end else value = tempPtr->data; delete tempPtr; length--; return true; // delete successful } // end else } // end function removeFromBack // is List empty? template< typename NODETYPE > bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; } // end function isEmpty // return pointer to newly allocated node template< typename NODETYPE > ListNode< NODETYPE > *List< NODETYPE >::getNewNode(const NODETYPE &value ) { return new ListNode< NODETYPE >( value ); } // end function getNewNode // display contents of List template< typename NODETYPE > void List< NODETYPE >::print() const { if ( isEmpty() ) { cout << "The list is empty\n\n"; return; } // end if ListNode< NODETYPE > *currentPtr = firstPtr; cout << "The list is: "; while ( currentPtr != 0 ) { cout << currentPtr->data << ' '; currentPtr = currentPtr->nextPtr; } // end while cout << "\n\n"; } // end function print template< typename NODETYPE > int List< NODETYPE >::numberOfElements() const { return length + 1; } template < typename NODETYPE> List< NODETYPE> & List< NODETYPE>:: operator = (const List< NODETYPE> &a) { while(!this ->isEmpty()) { int value; this ->removeFromBack(value); } ListNode< NODETYPE > *currentPtr = a.firstPtr; while(currentPtr != 0) { this -> insertAtBack(currentPtr->data); currentPtr = currentPtr->nextPtr; } return *this; } template < typename NODETYPE> int List< NODETYPE>:: operator < (const List< NODETYPE > &a) { if(length < a.length) return 1; return 0; } #endif // !defined(AFX_LIST_H__BC404E61_5B68_4FA2_82B5_99EB5C8DBFE5__INCLUDED_) Добавлено @ 14:35 говоря проще, то шаблоны исбвляют программиста, от перегузки функций для разных типов и написания классов для близких типов -------------------- Первый блин всегда похож на сферу, иногда бывает и куб. |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Учти что шаблоны в С++ создают перегруженные для каждого типа функции, твой результирующий бинарник раздувается.
По другому это работает в Java5 и C#, там все шаблоны приводятся к общему типу Object. Компилятор следит какие типы ты кладёшь в шаблон(ую функцию, класс и т.п.). В момент использования компилятор сам добавляет привидение типа к Object и обратно. Таким образом мы реально имеем всего одну функцию(метод) работающий со многими типами обьектов. Проблема: примитивы должны обращатся в обьекты оболочки(boxing), это убивает производительность. Вывод: а на кой хранить примитивы в контейнерах, мы ведь ООП используем -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Wowa |
|
|||
|
Эксперт Профиль Группа: Админ Сообщений: 15017 Регистрация: 14.9.2000 Где: Винград Репутация: нет Всего: 290 |
и все? для чего они еще могут быть полезны? |
|||
|
||||
| chipset |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4071 Регистрация: 11.1.2003 Где: Seattle, US Репутация: 27 Всего: 165 |
Вроде бы ни для чего. А что мало? Прикинь, надо былоб создавать для каждого класса класс... Вообще то, желательно заглядывать в таких вопросах в Страуструпа или стандарт, там точнее всего написано. pablo, используй плз. теги [code=cpp][/code]. Читать такую кашу глаза устают... --------------------
|
||||
|
|||||
| Borisff2003 |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 198 Регистрация: 26.2.2004 Где: г. Уфа Репутация: 1 Всего: 1 |
Ну например вся STL построенна на шаблонах Еще можешь почитать Andrei Alexandrescu (Андрей Александреску) Modern C++ Design (Современное проектирование на C++) http://anatolix.naumen.ru/Books/CPlusPlus?v=fvi --------------------
Лень, двигатель прогресса |
|||
|
||||
| Hroft |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 20.10.2003 Где: Москва Репутация: нет Всего: 3 |
Вот это точно. Великая книга.
Моя любимая идея оттуда - разбиение классов на стратегии: множественное наследование от параметров шаблона. Потрясающая гибкость. И еще - возможность определять, является ли тип указателем (да и много чем еще). Списки типов. В общем - Loki. |
|||
|
||||
| De Gray |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 128 Регистрация: 18.2.2005 Где: Регистрация? Репутация: нет Всего: 4 |
Определения является ли интерфейс желаемым интерфейсом(по сдвигу в VTable). Осталось только добавить, что с шаблонами каждый вызов функции превращается в довольно изощренное и долгое действо, что, есстессно, убивает производительность -- немного более изящный выход -- частичная спецификация. Не говоря уже о том, что вынос шаблона в отдельный модуль является довольно изощренной проблемой настроек многих компиляторов. --------------------
Извяните, шо мы к вас за поможите обращаимси. |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
шаблоны не влияют на процесс вызова функции: они пропадают сразу после компиляции -------------------- qqq |
|||
|
||||
| bel_nikita |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Эксперт Сообщений: 2304 Регистрация: 12.10.2003 Где: Поезд №21/22 ( ст . Прага ) Репутация: 21 Всего: 47 |
chipset
Только беда в том, что не фсе компиляторы поддерживают стандарт на фсе 100%
Ну и конечно, зависит под что затачиваем софт |
||||||
|
|||||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |