- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
- •Оглавление
- •Предисловие
- •Введение
- •1.1. Понятие класса и объекта. Инкапсуляция
- •1.2. Определение классов. Компоненты. Доступность
- •Class_key /*class_id*/ { /*members_list*/ };
- •Value_type class_id::function_id(parameters) {statements}
- •CPoint point1(100,70); // локальный объект
- •Static cPoint point3(50,120); // статический объект
- •Class_id(parameters) /*:initializer_list*/ {/*statements*/}
- •CString(const char *);
- •Delete[] __thematrix;
- •1.4. Обращение к компонентам объектов
- •1.5. Статические и нестатические компоненты классов
- •1.7. Указатель this
- •В опросы для самопроверки
- •2. Механизм наследования. Полиморфизм
- •2.1. Формы наследования. Базовые и производные классы
- •Class_key class_id: inheritance_specifier base_class_id {member_list};
- •2.3. Абстрактные классы
- •2.4. Множественное наследование и виртуальные классы
- •2.5. Преобразование динамических типов. Динамическая идентификация типов
- •Catch ( std::bad_cast & ) { // обработка исключения
- •Return 0;
- •Вопросы для самопроверки
- •3. Дружественные функции и классы
- •3.1. Дружественные функции
- •3.2. Дружественные классы
- •Вопросы для самопроверки
- •4. Механизм вложения
- •4.1. Вложенные классы
- •4.2. Локальные классы
- •Вопросы для самопроверки
- •5. Объектная модель и шаблоны
- •5.1. Определение, описание и инстанцирование шаблонов
- •::Function_id(function_parameter_list) { statements }
- •5.2. Параметры и аргументы шаблонов
- •Class identifier typename identifier
- •// Key, Data – параметры-типы (типы ключа и данных отображения)
- •// Container – контейнер, где содержится информация отображения class сMap {
- •Class MyTemplate
- •Int array[10]; struct Structure { int m; static int sm; } str;
- •5.3. Шаблоны компонентных функций
- •Value_type function_template_id(function_parameter_list) { statements }
- •::Function_template_id(function_parameter_list) { statements }
- •5.4. Специализация шаблонов
- •Вопросы для самопроверки
- •6. Перегрузка операций
- •Value_type operator @ (parameter_list);
- •Value_type operator @ (parameter_list) { statements }
- •Return fail();
- •6.3. Перегрузка бинарных операций
- •Value_type operator @ (parameter); // компонентная функция
- •Value_type operator @ (parameter, parameter); // глобальная функция friend value_type operator @ (parameter, parameter); // дружественная функция
- •Return *this;
- •Return *this;
- •/* Присваиваем собственные данные класса d */
- •6.4. Перегрузка операций управления памятью
- •Typedef void (*new_handler) ();
- •Extern new_handler set_new_handler( new_handler new_p );
- •Void operator delete(void * memory) {
- •... // Специальная обработка пользователя ::operator delete(memory); // освободить память
- •Вопросы для самопроверки
- •7. Механизм исключений
- •Throw expression
- •7.3. Специальные средства поддержки механизма исключений
- •Unexpected_function set_unexpected(unexpected_function func_name);
- •Typedef void (* unexpected_function) ();
- •Extern char * __throwExceptionName; extern char * __throwFileName; extern unsigned __throwLineNumber;
- •Вопросы для самопроверки
- •8. Подсчет ссылок
- •8.1. Назначение механизма подсчета ссылок
- •8.2. Контекстно-независимая модель счетчика ссылок
- •8.4. Внедрение подсчета ссылок в существующий класс
- •Вопросы для самопроверки
- •9. Стандартная библиотека шаблонов (stl)
- •9.1. Назначение и архитектура stl
- •9.2. Последовательные контейнеры
- •Class vector {
- •// Определение итераторов
- •Sort(first,last); // сортировка вектора в диапазоне итераторов
- •Ifstream ifile ("example.In"); ofstream ofile ("example.Out");
- •OutputIterator copy(
- •InputIterator first, InputIterator last, OutputIterator result );
- •// Заполнение списка
- •Operator- (int)
- •Operator- (random access iterator) operator[] (int)
- •InputIterator find(InputIterator first, InputIterator last, const t & value);
- •InputIterator find(InputIterator first, InputIterator last, const t & value)
- •Return first;
- •OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
- •Return result;
- •OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
- •Return result;
- •Void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
- •__Quick_sort_loop(first, last, comp); __final_insertion_sort(first, last, comp);
- •T accumulate(InputIterator first, InputIterator last, t init, Function f);
- •V.Push_back(2); V.Push_back(5);
- •9.5. Функторы
- •T operator()(const t & X) const { return -X; }
- •9.7. Адаптеры
- •S1.Push(1); s1.Push(5);
- •// Записать в вектор числа 1 2 3 4
- •// Сортировать по неубыванию
- •// Записать в вектор числа 4 6 10 3 13 2
- •Вопросы для самопроверки
- •Заключение
- •Библиографический Список
- •6Vpj7-h3cxh-hbtpt-x4t74-3yvy7
T accumulate(InputIterator first, InputIterator last, t init, Function f);
Здесь first и last задают диапазон значений итератора, а init устанавливает начальное значение (для аддитивных операций это 0, а для мультипликативных – 1), F – функтор, определяющий вид операции.
Пример
vector<int> v;
V.Push_back(2); V.Push_back(5);
cout << accumulate(v.begin(), v.end(), 10, divides<int>());
Кроме рассмотренных алгоритмов, четвертая группа включает также алгоритмы inner_product, partial_sum и adjacent_difference.
9.5. Функторы
Функтором в STL называют объект, класс которого инкапсулирует операцию функционального вызова operator(). Функторы удобно использовать для представления предикатов и других функций, передаваемых алгоритмам (выше в примерах мы уже несколько раз использовали функторы). Простейшими стандартными функторами являются функтор отрицания и функтор суммирования. Их определения даны ниже.
template <class T> // функтор отрицания
struct negate : unary_function<T, T> {
T operator()(const t & X) const { return -X; }
};
template <class T> // функтор суммирования
struct plus : binary_function<T, T, T> {
T operator()(const T & x, const T & y) const { return x + y; }
};
Шаблон negate, представляющий функтор отрицания, открыто наследует от шаблона unary_function, а шаблон plus, соответствующий функтору суммирования, – от шаблона binary_function. Сами эти шаблоны, по сути, не представляют классы, поскольку не определяют никакого поведения, а лишь вводят типы данных для аргументов и результата. Их определения имеют вид:
template <class Arg, class Result> struct unary_function
{
typedef Arg argument_type;
typedef Result result_type;
};
template <class Arg1, class Arg2, class Result> struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
Как шаблоны unary_function, binary_function, так и рассмотренные выше (и многие другие) функторы определены в заголовочном файле function.h. В этом файле имеется много разнообразных функторов, в частности, представляющие базовые логические операции, арифметические операции, операции сравнения.
Кроме стандартных функторов, любая программа может содержать определенные пользователем функторы. Примеры таких определений имеются выше. Ниже приведен еще один подобный пример. В нем определяется функтор prod_odd, который возвращает логическое значение. Оно индицирует, является ли произведение аргументов функтора нечетным числом. Сам функтор используется для поиска в списке первых двух смежных значений, произведение которых нечетно.
Пример
template <class T> class prod_odd {
public:
int operator() (const T & v1, const T & v2) {
return v1%2 != 0 && v2%2 != 0;
}
};
...
list<int> l;
// заполняем список значениями
...
list<int>::iterator i = // поиск стандартным алгоритмом adjacent_find
adjacent_find(l.begin(), l.end(), prod_odd<int>());
if (i != l.end())
cout << *i++ << " " *i++;
else cout << "таких значений в списке нет";
9.6. Ассоциативные контейнеры
Ассоциативные контейнеры – это особый вид контейнеров, которые позволяют быстро получать доступ к хранимым в них данным за счет использования механизма ключей. В STL определены следующие виды таких контейнеров: набор (set), мультинабор (multiset), отображение (map), мультиотображение (multimap). Все указанные контейнеры хранят данные сортированными, причем для обеспечения максимальной скорости получения данных в качестве «внутреннего» контейнера они используют дерево специального вида. Отличие между контейнерами set (map) и multiset (multimap) состоит в том, что set и map используют уникальные ключи для идентификации данных, а multiset и multimap нет. Для того чтобы включить поддержку рассматриваемых контейнеров, нужно подключить заголовочные файлы set.h и map.h соответственно.
Шаблон set инкапсулирует свойства и операции над упорядоченным набором объектов. Ключевые данные для упорядочения – сами хранимые объекты (т.е. хранимый объект – это и данные, и ключ). Параметрами шаблона являются: тип хранимых объектов (он же – тип ключа), функтор Compare, задающий способ упорядочения объектов (по умолчанию упорядочением управляет стандартный функтор less<T>), а также аллокатор, инкапсулирующий модель памяти программы. Число, порядок и назначение параметров шаблона multiset аналогичны (ключи в multiset, напомним, необязательно уникальны, т.е. multiset может содержать один и тот же объект многократно). Примеры определения набора и мультинабора даны ниже (создать контейнер рассматриваемых классов можно также из другого ассоциативного контейнера, или из последовательности элементов с указанием диапазона значений итератора).
Примеры
set < MyClass, greater<MyClass> > MyClassSet;
// порядок сортировки данных задается классом greater<MyClass>
multiset <MyClass> MyClassMultiSet;
// а здесь порядок задается классом less<MyClass> по умолчанию
Контейнеры set и multiset включают «типичные» для всех контейнеров компонентные функции begin, end, rbegin, rend, empty, size, max_size, swap и ряд других. Действие этих функций не отличается от действия их аналогов в последовательных контейнерах. Для перебора компонент set и multiset используют двунаправленные итераторы. Присваивание выполняется операцией operator =, а сравнение операцией operator ==. Добавление объектов производится функцией insert, удаление – функцией erase. К контейнерам set и multiset применимы теоретико-множественные операции, такие как пересечение, включение элемента, разность и т.д.
Пример
struct ltstr // функтор для сравнения объектов
{
bool operator()(const char * s1, const char * s2) const
{
return strcmp(s1, s2) < 0;
}
};
int main() {
const int N = 6;
const char * a[N] = {"aaa", "bbb", "ccc", "ddd", "eee", "fff"};
const char * b[N] = {"zzzz", "eee", "ddd", "tt", "ff", "uuu"};
// формируем наборы из массивов
set<const char *, ltstr> A(a, a + N);
set<const char *, ltstr> B(b, b + N);
// создаем пустой контейнер для результата
set<const char *, ltstr> C;
cout << "Набор A: ";
copy(A.begin(), A.end(), ostream_iterator<const char *>(cout, " "));
cout << endl;
cout << "Набор B: ";
copy(B.begin(), B.end(), ostream_iterator<const char *>(cout, " "));
cout << endl;
cout << "Объединение: ";
set_union(A.begin(), A.end(), B.begin(), B.end(),
ostream_iterator<const char *>(cout, " "), ltstr());
cout << endl;
cout << "Пересечение: ";
set_intersection(A.begin(), A.end(), B.begin(), B.end(),
ostream_iterator<const char *>(cout, " "), ltstr());
cout << endl;
set_difference(A.begin(), A.end(), B.begin(), B.end(),
inserter45(C, C.begin()), ltstr());
cout << "Набор C (разность A и B): ";
copy(C.begin(), C.end(), ostream_iterator<const char *>(cout, " "));
cout << endl;
return 0;
}
Важной особенностью контейнеров set и multiset является то, что вставка и удаление для них не нарушают корректность итераторов на другие элементы. Кроме того, из-за особого внутреннего представления контейнеров эти операции выполняются весьма быстро.
Шаблоны map и multimap содержат набор пар, в каждую из которых входят ключ и ассоциированный с ним объект. Параметризуются они четырьмя элементами: типом ключа, типом объекта, функтором сравнения (по умолчанию less<T>) и аллокатором. Примеры определения набора и мультинабора представлены ниже.
Примеры
map < int, MyClass, less<int> > MyClassMap;
multimap < int, MyClass, less<int> > MyClassMultiMap;
Базовые операции для map и multimap соответствуют операциям для set и multiset. Дополнительно шаблон map вводит операцию operator[], которая позволяет по ключу получить ассоциированный с ним объект. Шаблон multimap не вводит каких-либо новых операций.
Ниже приведен пример применения шаблона multimap.
struct ltstr // функтор для сравнения ключей
{
bool operator()(const char * s1, const char * s2) const
{
return strcmp(s1, s2) < 0;
}
};
int main() {
multimap<const char *, int, ltstr> m;
// вставка пар в мультиотображение
m.insert( pair<const char * const, int>("a", 1) );
m.insert( pair<const char * const, int>("c", 2) );
m.insert( pair<const char * const, int>("b", 3) );
m.insert( pair<const char * const, int>("b", 4) );
m.insert( pair<const char * const, int>("a", 5) );
m.insert( pair<const char * const, int>("b", 6) );
// выделение объектов с одинаковыми ключами
cout << "Число объектов с ключом a: " << m.count("a") << endl;
cout << "Число объектов с ключом b: " << m.count("b") << endl;
cout << "Число объектов с ключом c: " << m.count("c") << endl;
// вывод всех объектов
cout << "Элементы m: " << endl;
for ( multimap<const char *, int, ltstr>::iterator it = m.begin();
it != m.end(); ++it )
cout << " [" << (*it).first << ", "
<< (*it).second << "]" << endl;
}
В примере для представления вставляемых компонент использован шаблон pair, который инкапсулирует свойства упорядоченных пар разнотипных объектов. Определяется шаблон pair в заголовочном файле pair.h. Для удобства вместо явного вызова конструктора пар можно было бы использовать функцию make_pair, определенную в файле utility.h.
