}
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}

В этой программе тип VoidPtr определён как синоним void* .

«Ключевое словоtypedef создаёт новое имя для существующего типа. Вы можете везде, где видитеVoidPtr , в уме вставлятьvoid* . Использование таких замен делает текст более удобочитаемым, а также упрощает синтаксис выражений. Иногда оказывается невозможным заставить работать существующий шаблон класса с указателем, и тогда использованиеtypedef для замены составного типа наподобие указателя может решить проблему.»
[ Советы ]
_________________
315 стр. Глава 27. Шаблоны С++
Класс VoidVector предоставляет те же функции-члены add( ) и get( ) , что и TemplateVector из предыдущей программы.
Это решение имеет ( как минимум ) три проблемы. Во-первых, оно неудобно в использовании, как видно из текста функции main( ) — вы не в состоянии сохранить значение, и должны использовать только указатели на объекты. Это означает, что вы должны выделить для значения память в куче и поместить в вектор её адрес.
Во-вторых, если вдруг вы попытаетесь добавлять целые значения в вектор следующим образом:
int n ;
сin >> n ;
vv.add( ( void* ) & n ) ;
то у вас ничего не получится. Переменная n имеет локальную область видимости, так что при выходе из цикла for он просто потеряет всякий смысл.

«На самом деле всё ещё хуже — адресn остаётся неизменным во всех итерациях циклаfor .»
[ Советы ]
В-третьих, самая серьёзная проблема в том, что при получении значений из VoidVector вы должны знать их тип. С++ не может проверить тип объекта, чтобы убедиться, что ваши предположения верны. Допустим, вы решили, что в векторе хранятся не целые, а действительные числа, и использовали следующий код:
double dValue = *( double* )get( ) ;
Такая программа не будет работать корректно, поскольку в dValue в результате окажется какой-то мусор. Однако компиляция этой программы пройдёт без ошибок. Приведение типа к void* сводит на нет преимущества строгой типизации С++.
►Советы по использованию шаблонов...316
Вы должны знать некоторые особенности использования шаблонов. Во-первых, шаблон не генерирует никакого кода ( код генерируется только после преобразования в конкретный класс или функцию ). Именно по этой причине шаблоны практически никогда не размещают в .срр -файлах. Обычно полное определение шаблона класса, включая все функции-члены, располагается в заголовочном файле с тем, чтобы быть доступным компилятору в процессе его работы.
Во-вторых, шаблон класса не потребляет память. Следовательно, наличие шаблона класса никак не скажется на программе, если этот шаблон не будет инстанцирован. С другой стороны, шаблон класса использует память при каждом инстанцировании, поэтому несмотря на то, что, например, класс Array< int > уже существует, классу Array< Student > также потребуется память.
И наконец, шаблон класса не компилируется и не проверяется на наличие ошибок до тех пор, пока не будет преобразован в реальный класс. Таким образом, программа, содержащая Аггау< Т > , может нормально компилироваться, несмотря на наличие в шаблоне очевидных синтаксических ошибок. Эти ошибки никак не проявят себя до тех пор, пока не будут созданы реальные классы наподобие Array< int > или Array< Student > .
_________________
316 стр. Часть 5. Полезные особенности
Глава 28. СТАНДАРТНАЯ БИБЛИОТЕКА ШАБЛОНОВ...317
ОГЛАВЛЕНИЕ
В этой главе...
►Контейнер string 317
►Контейнер list 320
►Итераторы 321
►Использование контейнера map 324
Некоторые программы сразу же пересылают получаемые данные, однако большинству программ приходится сначала сохранять информацию. Структуры, которые используются для хранения данных, называются контейнерами или коллекциями ( в моей книге это взаимозаменяемые понятия ). Пока что мы с вами в основном для хранения данных использовали массивы. Массив в качестве контейнера обладает рядом привлекательных свойств, в частности, высокой скоростью сохранения и выборки данных. Кроме того, можно объявить массив для хранения данных любого типа. Тем не менее и у массива есть свои существенные недостатки.
Читать дальше