Стефан Дэвис - С++ для чайников .
- Название:С++ для чайников .
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс. Компьютерное издательство Диалектика
- Год:2007
- Город:Москва
- ISBN:0-7645-6852-3, 978-5-8459-0723-3
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стефан Дэвис - С++ для чайников . краткое содержание
1
empty-line
4
С++ для чайников . - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
return array[ nReadIndex++ ] ;
}
protected :
int nSize ;
int nWriteIndex ;
int nReadIndex ;
T* array ;
} ;
/* Работа с двумя векторами — целых чисел и имён */
void intFn( ) ;
void nameFn( ) ;
int main( int argc , char* pArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */
intFn( ) ;
nameFn( ) ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
/* Работа с целыми числами */
void intFn( )
{
/* Создание вектора */
TemplateVector< int > integers( 10 ) ;
/* Добавляем значения в вектор */
cout << "Введите последовательность целых чисел\n"
"для внесения в вектор ( отрицательное\n"
"число завершает ввод последовательности )"
<< endl ;
for ( ; ; )
{
int n ;
cin >> n ;
if ( n < 0 ) { break ; }
integers.add( n ) ;
}
cout << "\nВы ввели следующие числа" << endl ;
for ( int i = 0 ; i < integers.size( ) ; i++ )
{
cout << i << ":" << integers.get( ) << endl ;
}
}
/* Работа с именами */
class Name
{
public :
Name( char* n = " " ) : name( n ) { }
_________________
312 стр. Часть 5. Полезные особенности
string display( ) { return name ; }
protected :
string name ;
} ;
void nameFn( )
{
/* Создание вектора */
TemplateVector< Name > names( 10 ) ;
/* Добавление значений в вектор */
cout << "Введите имена\n"
<< "('х' для завершения ):" << endl ;
for ( ; ; )
{
char buffer[ 80 ] ;
do
{
cin.getline( buffer , 80 ) ;
} while ( strlen( buffer ) == 0 ) ;
if ( stricmp( buffer , "x" ) == 0 )
{
break ;
}
names.add( Name( buffer ) ) ;
}
cout << "\nВы ввели имена" << endl ;
for ( int i = 0 ; i < names.size( ) ; i++ )
{
Name name = names.get( ) ;
cout << i << ":" << name.display( ) << endl ;
}
}
Шаблон класса TemplateVector< T > содержит массив объектов класса Т . Шаблон класса имеет две функции-члена: add( ) и get( ) . Первая из них добавляет объект типа Т в очередное пустое место массива, а вторая — возвращает следующий элемент из массива.
Приведённая программа инстанцирует этот шаблон сначала для типа int . а затем для пользовательского класса Name .
Функция intFn( ) создаёт вектор целых чисел с 10 элементами, после чего считывает вводимые пользователем числа в вектор, а потом выводит их на экран, используя функции, предоставляемые шаблоном TemplateVector .
Вторая функция, nameFn( ) , создаёт вектор объектов типа Name . Функция так же размещает пользовательский ввод в векторе, а потом выводит его элементы на экран.
Обратите внимание, как шаблон TemplateVector позволяет с одинаковой простотой работать как со встроенным типом, так и с пользовательским классом. Вот как выглядит пример работы данной программы.
Введите последовательность целых чисел
для внесения в вектор ( отрицательное число
завершает ввод последовательности )
5
10
15
-1
Вы ввели следующие числа
0:5
1:10
2:15
Введите имена
('х' для завершения ):
Igor
Ira
Anton
x
Вы ввели имена
0: Igor
1: Ira
2 : Anton
Press any key to continue...
_________________
313 стр. Глава 27. Шаблоны С++
►Зачем нужны шаблоны классов...314
"Неужели я не могу просто создать класс Array ? — скажете вы. — Зачем мне возиться с шаблонами?"
Конечно, можете. Если заранее знаете, объекты какого типа будут храниться в этом массиве. Например, если вам нужен только массив целых чисел, то нет смысла ломать голову над шаблоном Vector< T > — проще создать класс IntArray и использовать его.
По сути единственной альтернативой шаблонам является использование void*, указателя, который может указывать на объекты любого типа. Этот способ использован в следующей программе.
/* VoidVector — реализация вектора с использованием */
/* void* для хранения элементов */
#include
#include
#include
using namespace std ;
typedef void* VoidPtr ;
class VoidVector
{
public:
VoidVector( int nArraySize )
{
/* Количество элементов */
/* Количество элементов */
nSize = nArraySize ;
ptr = new VoidPtr[ nArraySize ] ;
reset( ) ;
}
int size( ) { return nWriteIndex ; }
void reset( ) { nWriteIndex = 0 ; nReadIndex = 0 ; }
void add( void* pValue )
{
if ( nWriteIndex < nSize )
{
ptr[ nWriteIndex++ ] = pValue ;
_________________
314 стр. Часть 5. Полезные особенности
}
}
VoidPtr get( ){ return ptr[ nReadIndex++ ] ; }
protected :
int nSize ;
int nWriteIndex ;
int nReadIndex ;
VoidPtr* ptr ;
} ;
int main( int argc , char* pArgs[ ] )
{
setlocale ( LC_ALL , ".1251" ) ; /* печать русских текстов */
/* Создание вектора */
VoidVector vv( 10 ) ;
/* Добавление значений к вектору */
cout << "Введите последовательность целых чисел\n"
"для внесения в вектор ( отрицательное\n"
"число завершает ввод последовательности )"
<< endl ;
for( ; ; )
{
int* p = new int ;
cin >> *p ;
if ( *p < 0 )
{
delete p ;
break ;
}
vv.add( ( void* ) p ) ;
}
cout << "\nВы ввели следующие числа" << endl ;
for ( int i = 0 ; i < vv.size( ) ; i++ )
{
int* p = ( int* )vv.get( ) ;
cout << i << ":" << *p << endl ;
}
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
В этой программе тип VoidPtr определён как синоним void* .
«Ключевое словоtypedef создаёт новое имя для существующего типа. Вы можете везде, где видитеVoidPtr , в уме вставлятьvoid* . Использование таких замен делает текст более удобочитаемым, а также упрощает синтаксис выражений. Иногда оказывается невозможным заставить работать существующий шаблон класса с указателем, и тогда использованиеtypedef для замены составного типа наподобие указателя может решить проблему.»
[ Советы ]
_________________
315 стр. Глава 27. Шаблоны С++
Класс VoidVector предоставляет те же функции-члены add( ) и get( ) , что и TemplateVector из предыдущей программы.
Это решение имеет ( как минимум ) три проблемы. Во-первых, оно неудобно в использовании, как видно из текста функции main( ) — вы не в состоянии сохранить значение, и должны использовать только указатели на объекты. Это означает, что вы должны выделить для значения память в куче и поместить в вектор её адрес.
Читать дальшеИнтервал:
Закладка: