С.Б. Липпман, Ж. Лажойе - Язык программирования С++ Вводный курс (1114944), страница 14
Текст из файла (страница 14)
Дляэтого существует директива using:#include "IBM_Canada_Laboratory.h"using namespace IBM_Canada_Laboratory;int main(){// IBM_Canada_Laboratory::MatrixMatrix mat(4,4);// IBM_Canada_Laboratory::ArrayArray<int> ia(1024);// ...}Пространство имен IBM_Canada_Laboratory становится видимым в программе. Можносделать видимым не все пространство, а отдельные имена внутри него (селективнаядиректива using):#include "IBM_Canada_Laboratory.h"using namespace IBM_Canada_Laboratory::Matrix;// видимым становится только Matrixint main(){// IBM_Canada_Laboratory::MatrixMatrix mat(4,4);// Ошибка: IBM_Canada_Laboratory::Array невидимArray<int> ia(1024);// ...}Как мы уже упоминали, все компоненты стандартной библиотеки С++ объявлены внутрипространства имен std.
Поэтому простого включения заголовочного файла недостаточно,чтобы напрямую пользоваться стандартными функциями и классами:#include <string>// ошибка: string невидимstring current_chapter = "Обзор С++";66С++ для начинающихНеобходимо использовать директиву using:#include <string>using namespace std;// Ok: видим stringstring current_chapter = "Обзор С++";Заметим, однако, что таким образом мы возвращаемся к проблеме “засорения”глобального пространства имен, ради решения которой и был создан механизм#include <string>именованных пространств.
Поэтому лучше использовать либо квалифицированное имя:// правильно: квалифицированное имяstd::string current_chapter = "Обзор С++";либо селективную директиву using:#include <string>using namespace std::string;// Ok: string видимstring current_chapter = "Обзор С++";Мы рекомендуем пользоваться последним способом.В большинстве примеров этой книги директивы пространств имен были опущены. Этосделано ради сокращения размера кода, а также потому, что большинство примеров былискомпилированы компилятором, не поддерживающим пространства имен – достаточнонедавнего нововведения С++.
(Детали применения using-объявлений при работе сстандартной библиотекой С++ обсуждаются в разделе 8.6.)В нижеследующих главах мы создадим еще четыре класса: String, Stack, List имодификацию Stack. Все они будут заключены в одно пространство имен –Cplusplus_Primer_3E. (Более подробно работа с пространствами имен рассматриваетсяв главе 8.)Упражнение 2.21namespace Exercize {Дано пространство именtemplate <class elemType>class Array { ... };template <class EType>void print (Array< EType > );class String { ...
}template <class ListType>class List { ... };}и текст программы:67С++ для начинающихint main() {const int size = 1024;Array<String> as (size);List<int> il (size);// ...Array<String> *pas = new Array<String>(as);List<int> *pil = new List<int>(il);print (*pas);}Программа не компилируется, поскольку объявления используемых классов заключены впространство имен Exercise. Модифицируйте код программы, используя(a) квалифицированные имена(b) селективную директиву using(c) механизм псевдонимов(d) директиву using2.8. Стандартный массив – это векторХотя встроенный массив формально и обеспечивает механизм контейнера, он, как мывидели выше, не поддерживает семантику абстракции контейнера.
До принятиястандарта C++ для программирования на таком уровне мы должны были либоприобрести нужный класс, либо реализовать его самостоятельно. Теперь же классмассива является частью стандартной библиотеки C++. Только называется он не массив,а вектор.Разумеется, вектор реализован в виде шаблона класса. Так, мы можем написатьvector<int> ivec(10);vector<string> svec(10);Есть два существенных отличия нашей реализации шаблона класса Array от реализациишаблона класса vector. Первое отличие состоит в том, что вектор поддерживает какприсваивание значений существующим элементам, так и вставку дополнительныхэлементов, то есть динамически растет во время выполнения, если программист решилвоспользоваться этой его возможностью. Второе отличие более радикально и отражаетсущественное изменение парадигмы проектирования.
Вместо того чтобы поддержатьбольшой набор операций-членов, применимых к вектору, таких, как sort(), min(),max(), find()и так далее, класс vector предоставляет минимальный набор: операциисравнения на равенство и на меньше, size() и empty(). Более общие операции,перечисленные выше, определены как независимые обобщенные алгоритмы.Для использования класса vector мы должны включить соответствующий заголовочныйфайл.#include <vector>68С++ для начинающих// разные способы создания объектов типа vectorvector<int> vec0; // пустой векторconst int size = 8;const int value = 1024;// вектор размером 8// каждый элемент инициализируется 0vector<int> vec1(size);// вектор размером 8// каждый элемент инициализируется числом 1024vector<int> vec2(size,value);// вектор размером 4// инициализируется числами из массива iaint ia[4] = { 0, 1, 1, 2 };vector<int> vec3(ia,ia+4);// vec4 - копия vec2vector<int> vec4(vec2);Так же, как наш класс Array, класс vector поддерживает операцию доступа по индексу.#include <vector>Вот пример перебора всех элементов вектора:extern int getSize();void mumble(){int size = getSize();vector<int> vec(size);for (int ix=0; ix<size; ++ix)vec[ix] = ix;// ...}Для такого перебора можно также использовать итераторную пару.
Итератор – этообъект класса, поддерживающего абстракцию указательного типа. В шаблоне классаvector определены две функции-члена – begin() и end(), устанавливающие итераторсоответственно на первый элемент вектора и на элемент, который следует за последним.Вместе эти две функции задают диапазон элементов вектора. Используя итератор,#include <vector>предыдущий пример можно переписать таким образом:extern int getSize();void mumble(){int size = getSize();vector<int> vec(size);69С++ для начинающих70vector<int>::iterator iter = vec.begin();for (int ix=0; iter!=vec.end(); ++iter, ++ix)*iter = ix;// ...}Определение переменной itervector<int>::iterator iter = vec.begin();инициализирует ее адресом первого элемента вектора vec. iterator определен спомощью typedef в шаблоне класса vector, содержащего элементы типа int. Операцияинкремента++iterперемещает итератор на следующий элемент вектора.
Чтобы получить сам элемент,нужно применить операцию разыменования:*iterВ стандартной библиотеке С++ имеется поразительно много функций, работающих склассом vector, но определенных не как функции-члены класса, а как наборобобщенных алгоритмов. Вот их неполный перечень:алгоритмы поиска: find(), find_if(),count_if();search(), binary_search(), count(),алгоритмы сортировки и упорядочения: sort(), partial_sort(),partition(), rotate(), reverse(), random_shuffle();merge(),алгоритмы удаления: unique(), remove();численныеалгоритмы:adjacent_difference();accumulate(),алгоритмы генерации и измененияtransform(), copy(), for_each();partial_sum(),последовательности:inner_product(),generate(),fill(),алгоритмы сравнения: equal(), min(), max().В число параметров этих обобщенных алгоритмов входит итераторная пара, задающаядиапазон элементов вектора, к которым применяется алгоритм.
Скажем, чтобыупорядочить все элементы некоторого вектора ivec, достаточно написать следующее:sort ( ivec.begin(), ivec.end() );Чтобы применить алгоритм sort() только к первой половине вектора, мы напишем:sort ( ivec.begin(), ivec.begin() + ivec.size()/2 );Роль итераторной пары может играть и пара указателей на элементы встроенногомассива. Пусть, например, нам дан массив:С++ для начинающихint ia[7] = { 10, 7, 9, 5, 3, 7, 1 };Упорядочить весь массив можно вызовом алгоритма sort():sort ( ia, ia+7 );Так можно упорядочить первые четыре элемента:sort ( ia, ia+4 );Для использования алгоритмов в программу необходимо включить заголовочный файл#include <algorithm>Ниже приведен пример программы, использующей разнообразные алгоритмы вприменении к объекту типа vector:71С++ для начинающих72#include <vector>#include <algorithm>#include <iostream>int ia[ 10 ] = {51, 23, 7, 88, 41, 98, 12, 103, 37, 6};int main(){vector< int > vec( ia, ia+10 );vector<int>::iteratorit = vec.begin(),end_it = vec.end();cout << "Начальный массив: ";for ( ; it != end_it; ++ it ) cout << *it << ' ';cout << "\n";// сортировка массиваsort( vec.begin(), vec.end() );cout << "упорядоченный массив:";it = vec.begin(); end_it = vec.end();for ( ; it != end_it; ++ it ) cout << *it << ' ';cout << "\n\n";int search_value;cout << "Введите значение для поиска: ";cin >> search_value;// поиск элементаvector<int>::iterator found;found = find( vec.begin(), vec.end(), search_value );if ( found != vec.end() )cout << "значение найдено!\n\n";else cout << "значение найдено!\n\n";// инвертирование массиваreverse( vec.begin(), vec.end() );cout << "инвертированный массив: ";it = vec.begin(); end_it = vec.end();for ( ; it != end_it; ++ it ) cout << *it << ' ';cout << endl;}Стандартная библиотека С++ поддерживает и ассоциативные массивы.
Ассоциативныймассив – это массив, элементы которого можно индексировать не только целымичислами, но и значениями любого типа. В терминологии стандартной библиотекиассоциативный массив называется отображением (map). Например, телефонныйсправочник может быть представлен в виде ассоциативного массива, где индексами#include <map>служат фамилии абонентов, а значениями элементов – телефонные номера:#include <string>#include "TelephoneNumber.h"С++ для начинающих73map<string, telephoneNum> telephone_directory;(Классы векторов, отображений и других контейнеров в подробностях описываются вглаве 6. Мы попробуем реализовать систему текстового поиска, используя эти классы. Вглаве 12 рассмотрены обобщенные алгоритмы, а в Приложении приводятся примеры ихиспользования.)В данной главе были очень бегло рассмотрены основные аспекты программирования наС++, основы объектно-ориентированного подхода применительно к данному языку ииспользование стандартной библиотеки.