Теперь, вооружившись знаниями о динамическом выделении памяти, реализуем с помощью класса более «умный» массив числового типа. Встроенные массивы слишком просты и ненадежны. Наш массив должен быть «поумнее» — нужно обеспечить проверку индекса при обращении к элементу массива. И конечно, такой «массив» можно будет передавать в функции любым из возможных способов (по значению, по ссылке, по указателю) и возвращать в качестве результата.
Операции, которые со встроенными массивами должны выполняться в цикле, можно «упрятать» внутрь соответствующих методов и перегруженных операций. Например, практически обязательно реализовать операцию присваивания, чтобы можно было писать так:
а = Ь;
Запись совершенно естественная и понятная любому программисту: массив а становится копией массива Ь. Для числового массива естественно реализовать также арифметические операции. Например, умножение каждого элемента массива на некоторый коэффициент может выглядеть так:
а *= 1.34:
Здесь, очевидно, а является «умным» массивом, каждый элемент которого умножается на число 1.34. Ту же операцию можно реализовать с двумя массивами, например:
а *= Ь:
Это выражение представляет собой умножение элементов массива а на соответствующие элементы массива Ь. Если размер массива вычисляется методом s i ze (), то операция реализуется с помощью простого цикла:
if (a. size () == b. size О) for (int i = 0: i < a.sizeO: ++i) a[i] = a[i] * b[i]:
Очевидно, «упрятывание» операций существенно упростит работу с массивами и значительно повысит надежность программ. Инкапсуляция (и полиморфизм!) — в действии!
Набор операций с «умным» массивом может быть очень широким — все зависит от требований задачи и фантазии разработчика. Например, сортировку можно реализовать, перегрузив подходящую унарную операцию (например, ~ или !). Единственным аргументом такой операции, очевидно, является текущий объект — «умный» массив.
Реализуем массив с элементами типа double, а тип самого массива пусть называется ТАггау. Возможный интерфейс класса приведен в листинге 5.2. Как обычно, пусть операции с присваиванием являются методами класса, а соответствующие операции без присваивания — дружественными функциями. Операция индексирования указана дважды, как и в классе TString.
Листинг 5.2. Интерфейс «умного» массива
class ТАггау { public:
typedef unsigned int Uint: // дпя краткости
// конструкторы
TArray(Uint size, double k=0.0);
TArray(const double *begin, const double *end);
TArray(const ТАггау &a); // конструктор копирования
TArray(const ТАггау &a. Uint begin, Uint k);
~TArray(); // деструктор
Листинг 5.2 (продолжение)
II индексирование
double& operator[](Uint index);
const double& operator[](Uint index) const; // присваивание
TArray& operator=(const TArray &rhs);
TArray& assign(const TArray &a, Uint begin, Uint k);
TArray& assign(const double *begin, const double *end); // Медоды-операции
// аргумент - выражение
// аргумент - массив
// количество элементов
"левая" функция "левая" функция сумма всех элементов сумма элементов произведение всех элементов произведение элементов сортировка
поиск - "левая" функция
// // // // // // // //
Uint r); Uint r);
TArray& operator+=(const double &a); TArray& operator-=(const double &a); TArray& operator*=(const double &a); TArray& operator/=(const double &a); TArray& operator%=(const double &a); TArray& operator+=(const TArray &rhs) TArray& operator-=(const TArray &rhs) TArray& operator*=(const TArray &rhs) TArray& operator/=(const TArray &rhs) TArray& operator%=(const TArray &rhs) Uint size() const; double& max_value(); double& min_value(); double summa(); double summa(Uint I double product(); double product(Uint I void operator!(); double* find(const double &a);
const TArray &а); TArray &а);
// динамический массив // количество элементов
// скалярное произведение массивов friend double product_dot(const TArray &a, const TArray &b) friend TArray operator+(const TArray&a, const TArray &b) friend TArray operator*(const TArray&a, const TArray &b) friend TArray operator-(const TArray&a, const TArray &b) friend TArray operator/(const TArray&a, const TArray &b) friend TArray operator%(const TArray&a, const TArray &b) friend ostream& operator <<(ostream& to friend istream& operator >>(istream& to private:
double *data; Uint size_array;
};
|