Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Реализация с использованием библиотеки шаблонов

Использование библиотеки шаблонов С++ – ещё один вариант построения надёжного кода, позволяющего минимизировать затраты на разработку и избежать ошибок, связанных с реализацией системных функций управления памятью. В качестве недостатка такого подхода можно отметить несколько худшее быстродействие, так как код библиотеки шаблонов делается универсальным и, как правило, изобилует различными проверками и вызовами вспомогательных функций. Среди широко применяемых библиотек шаблонов можно отметить STL, Boost, Qt. Первая из них входит в стандарт С++, являясь частью языка, поэтому пример реализации приводится именно на её основе.

Все библиотеки шаблонов предоставляют готовые реализации программных контейнеров с различной организацией хранения данных в памяти и доступа к ним – вектор, список, очередь, ассоциативный массив и т.д., причём тип данных может быть любым (за счёт представления таких контейнеров в виде типизированных шаблонов классов).

Классы TVector и TMatrix модуля библиотеки векторной, матричной и кватернионной алгебр целесообразно построить на основе шаблона std::vector, объявленного в стандартном заголовочном файле vector. Объявление и реализация класса TQuaternion будут полностью аналогичны описанным в разделе 3.2.1 и здесь не рассматриваются.

Для расширения функциональности класса std::vector алгебраическими методами можно применить один из двух классических подходов. Первый из них – наследование, он предполагает объявление пользовательских классов как наследников от класса-шаблона с указанным типом параметра. Для вектора типом параметра может быть double или long double (в зависимости от платформы и необходимой точности вычислений), а для матрицы можно использовать вложенную параметризацию шаблона – в качестве типа использовать ранее объявленный параметризованный шаблон вектора (см. листинг 11, типы BaseVector и BaseMatrix соответственно). Это обеспечит «двумерность» массива для хранения содержимого матрицы.

Второй подход основан на агрегировании самостоятельными пользовательскими классами вектора и матрицы поля типа std::vector. Данный подход требует более обширного применения методов-декораторов (транслирующих вызовы методам агрегированного объекта и возвращающих назад результаты их работы) в пользовательских классах, при этом не давая никаких преимуществ. Подход же, связанный с наследованием, позволяет минимизировать декорирование, по существу обеспечивая лишь расширение уже имеющегося функционала класса std::vector алгебраическими операциями. В случае с матрицей преимущество не так очевидно, так как для защиты объектов матриц от некорректного использования (например, изменение длин отдельных строк) приходится использовать защищённое наследование, скрывающее все публичные методы класса std::vector. Это требует применения декорирования, аналогичного схеме с агрегированием.

Учитывая приведенные соображения, рассмотрим пример объявления классов TVector и TMatrix с их наследованием от класса-шаблона std::vector.

Листинг 11

#include <vector>

namespace StdLinearAlgebra {

// Базовые типы-шаблоны

typedef std::vector< double > BaseVector;

typedef std::vector< BaseVector > BaseMatrix;

// Опережающая декларация

class TMatrix;

// Класс векторов

class TVector: public BaseVector {

public:

// Конструктор по умолчанию

TVector(): BaseVector() {}

// Конструктор с заданным кол-вом элементов

TVector(int n): BaseVector(n) {}

// Конструктор копий

TVector(const TVector& rvalue): BaseVector(rvalue) {}

// Функция получения индекса последнего элемента

inline int high() const { return size() - 1; }

// Оператор - унарный минус

TVector operator - () const;

// Оператор вычитания векторов

TVector operator - (const TVector& arg) const;

// Оператор сложения векторов

TVector operator + (const TVector& arg) const;

// Оператор умножения вектора на число

TVector operator * (double arg) const;

// Оператор скалярного умножения векторов

double operator * (const TVector& arg) const;

// Оператор умножения вектора на матрицу

TVector operator * (const TMatrix& arg) const;

// Оператор умножения вектора на кватернион

//TQuaternion operator * (const TQuaternion& arg) const;

// Оператор векторного умножения векторов

TVector operator ^ (const TVector& arg) const;

// Дружественная функция - оператор умножения числа на вектор

friend TVector operator * (double lvalue, const TVector& rvalue);

// Функция получения модуля вектора

double length() const;

// Функция нормирования вектора

TVector& norm();

// Поворот вектора вокруг заданной оси на заданный угол при помощи формулы Родрига

//TVector rotateByRodrigFormula(double phi, const TVector& axis) const;

// Поворот вектора вокруг заданной оси на заданный угол при помощи кватерниона

//TVector rotate(double phi, const TVector& axis) const;

// Поворот вектора при помощи заданного кватерниона

//TVector rotateByQuaternion(const TQuaternion& L) const;

};

// Класс матриц

class TMatrix: protected BaseMatrix {

public:

// Конструктор по умолчанию

TMatrix(): BaseMatrix() {}

// Конструктор с заданным кол-вом элементов

TMatrix(int n, int m): BaseMatrix() { this ->resize(n, m); }

// Конструктор копий

TMatrix(const TMatrix& arg): BaseMatrix(arg) {}

// Функция получения количества строк

inline int rowCount() const { return this ->size(); }

// Функция получения кол-ва столбцов

inline int colCount() const { return (this ->size() > 0)? (* this)[0].size(): 0;}

// Функция получения индекса последней строки

inline int rowHigh() const { return rowCount() - 1; }

// Функция получения индекса последнего столбца

inline int colHigh() const { return colCount() - 1; }

// Оператор доступа к элементам матрицы

inline double& operator ()(int i, int j) { return (* this)[i][j]; }

// Оператор константного доступа к элементам матрицы

inline const double& operator ()(int i, int j) const { return (* this)[i][j]; }

// Константный оператор доступа к строке матрицы как к вектору

inline const TVector& operator () (int i) const { return (TVector&)(* this)[i]; }

// Изменение размера

void resize(int n, int m);

// Оператор - унарный минус

TMatrix operator - () const;

// Оператор вычитания матриц

TMatrix operator - (const TMatrix& arg) const;

// Оператор сложения матриц

TMatrix operator + (const TMatrix& arg) const;

// Оператор умножения матрицы на число

TMatrix operator * (double arg) const;

// Оператор умножения матриц

TMatrix operator * (const TMatrix& arg) const;

// Оператор умножения матрицы на вектор

TVector operator * (const TVector& arg) const;

// Дружественная функция - оператор умножения числа на матрицу

friend TMatrix operator * (double lvalue, const TMatrix& rvalue);

// Оператор обращения матриц (метод Гаусса)

TMatrix operator! () const throw (int);

// Функция вычисления детерминанта

double det() const;

// Функция транспонирования

TMatrix t() const;

// Функция формирования единичной матрицы

static TMatrix E(int n);

// Функция перестановки строк

TMatrix& swapRows(int i, int j);

}; }

Чтобы избежать совпадения наименований, объявление вспомогательных типов BaseVector, BaseMatrix и классов TVector, TMatrix делается в пространстве имён StdLinearAlgebra.

Следует также обратить внимание на уже упомянутый приём – защищённое наследование класса TMatrix от BaseMatrix, предотвращающее прямой доступ извне к публичным методам и свойствам класса std::vector как предка TMatrix. Главным образом этот приём нацелен на оператор BaseMatrix:: operator [] (int), который в противном случае позволял бы получить безконтрольный доступ к строкам матрицы как к отдельным объектам, менять размер и даже удалять их. Нужно отметить, что допустимо отдельно осуществить перегрузку этого оператора в защищённой или закрытой секции, чтобы запретить доступ к нему.

Реализация алгебраических методов для классов векторов, матриц и кватернионов полностью аналогична реализации, описанной в предыдущем разделе. Все служебные функции, предназначенные для работы с памятью, реализованы в классе std::vector, необходимая декорация этих методов и операторов выполняется непосредственно в заголовочном файле в виде встроенных (inline) методов, как например inline int TMatrix::rowCount() const – метод получения количества строк матрицы.

Премущества данного подхода к построению модуля библиотеки процедур векторной, матричной и кватернионной алгебр обусловлены высокой надёжностью и компактностью кода, отсутствием трудозатрат на разработку и отладку служебных функций. К уже упоминаемым недостаткам можно отнести меньшее быстродействие по сравнению с самостоятельной реализацией методов управления памятью.

Литература

1. Амелькин Н.И. Кинематика и динамика твердого тела (кватернионное изложение). – М.: МФТИ (ГУ), 2000. – 64 с.

2. Бесекерский В. А., Попов Е.П. Теория Систем автоматического управления. – Изд. 4-е, перераб. и доп. – Спб.: Профессия, 2003. – 752 с.

3. Бобронников В. Т., Красильщиков М. Н., Козорез Д. А. и др. Статистическая динамика и оптимизация управления летательных аппаратов: учебное пособие. / Под общ. ред. М. Н. Красильщикова, В. В. Малышева. – Изд. 2-е, перераб. и доп. – М.: Альянс, 2013. – 468 с.

4. Бранец В. Н., Шмыглевский И. П. Применение кватернионов в задачах ориентации твердого тела. – М.: Наука, 1973. – 320 с.

5. Вержбицкий В.М. Основы численных методов: Учебник для вузов. – М.: Высшая школа, 2002. – 840 с.

6. Желтов С.Ю., Веремеенко К.К., Ким Н.В. и др. Современные информационные технологии в задачах навигации и наведения беспилотных маневренных летательных аппаратов. / Под ред. М.Н. Красильщикова, Г.Г. Себрякова. – М.: ФИЗМАТЛИТ, 2009. – 556 с.

7. Осипов Д.Л. – Delphi. Программирование для Windows, OS X, iOS и Android. – Спб.: БХВ-Петербург, 2014. – 464 с.

8. Рашевский П. К. Риманова геометрия и тензорный анализ. – М.: Наука, 1967. – 664 с.

9. Страуструп Б. Программирование: принципы и практика с использованием С++. – Второе издание. – М.: Вильямс, 2016. – 1328 с.

10. Умнов А. Е., Аналитическая геометрия и линейная алгебра: учебное пособие. – 3-е изд., испр. и доп. – М.: МФТИ, 2011. – 554 с.

11. Элджер Дж. С++: Библиотека программиста. – Спб.: Питер, 1999. – 320 с.

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...