На этом шаге мы рассмотрим реализацию интерфейсного класса для массива.
В своей книге "The C++ Programming Language", 3rd Edition, Бьярн Страуструп описывает очень полезный интерфейсный класс для обычных массивов. Он гораздо надежнее обычных массивов, хотя и не уступает им по быстродействию. Наконец, он является хорошим примером контейнера STL, определяемого пользователем. В данном случае используется вариант с интерфейсным классом, то есть стандартный контейнерный интерфейс реализуется как оболочка вокруг массива. Определение класса саггау (сокращенное от "С array" или "constant size array") выглядит так:
#include <cstddef> template<class T,std::size_t thesize> class carray { private: T v[thesize]; // Массив фиксированного размера // для элементов типа Т public: // Определения типов typedef T value_type; typedef T* iterator; typedef const T* const_iterator; typedef T& reference; typedef const T& const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; // Поддержка итераторов iterator begin() { return v; } const_iterator begin() const { return v; } iterator end() { return v+thesize; } const_iterator end() const { return v+thesize; } // Прямой доступ к элементам reference operator[] (std::size_t i) { return v[i]; } const_reference operator[](std::size_t i) const { return v[i]; } // Фиксированный размер size_type size() const { return thesize; } size_type max_size() const { return thesize; } // Преобразование к обычному массиву T* as_array() { return v; } };
Пример использования класса carray:
//--------------------------------------------------------------------------- #include <vcl.h> #include <algorithm> #include <functional> #include <string> #include <iostream> #include "carray.hpp" #include <conio.h> //необходимо для getch() #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused using namespace std; std::string ToRus(const std::string &in) { char *buff = new char [in.length()+1]; CharToOem(in.c_str(),buff); std::string out(buff); delete [] buff; return out; } template <class T> inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="") { typename T::const_iterator pos; std::cout << ToRus(optcstr); for (pos=coll.begin(); pos!=coll.end(); ++pos) { std::cout <<*pos <<' '; } std::cout << std::endl; } int main(int argc, char* argv[]) { carray<int,10> a; for (unsigned i=0; i<a.size(); ++i) { a[i] = i+1; } cout << ToRus("Исходный массив:\n"); PRINT_ELEMENTS(a); reverse (a.begin(),a.end()); cout << ToRus("Массив в обратном порядке:\n"); PRINT_ELEMENTS(a); transform(a.begin(),a.end(), // Источник a.begin(), // Приемник negate<int>()); // Операция cout << ToRus("Массив противоположных чисел:\n"); PRINT_ELEMENTS(a); getch(); return 0; } //---------------------------------------------------------------------------
Как видно из приведенного кода, прямое взаимодействие с контейнером осуществляется через операции общего контейнерного интерфейса (функции begin(), end() и оператор []). Следовательно, в вашем распоряжении также оказываются различные операции, вызывающие функции begin() и end(), - такие, как алгоритмы и вспомогательная функция PRINT_ELEMENTS().
Результат выполнения программы выглядит так:
Рис.1. Результат работы приложения
На следующем шаге мы рассмотрим хэш-таблицы.