Иерархия классов
Эта страница объясняет структуру основных классов в иерархии классов Eigen и как они взаимодействуют. Пользователям, не занимающимся глубоким изучением, вероятно, эти детали не нужны, но они могут быть полезны как продвинутым пользователям, так и разработчикам Eigen.
Принципы
Иерархия классов Eigen разработана таким образом, чтобы избегать виртуальных функций, где их накладные расходы существенно ухудшали бы производительность. Вместо этого Eigen достигает полиморфизма с помощью шаблона Curiously Recurring Template (CRTP). В этом шаблоне базовый класс (например, MatrixBase) на самом деле является шаблонным классом, а производный класс (например, Matrix) наследуется от базового класса с самим производным классом в качестве аргумента шаблона (в данном случае Matrix наследуется от MatrixBase<Matrix>). Это позволяет Eigen разрешать вызовы полиморфных функций во время компиляции.
Кроме того, в разработке избегается множественное наследование. Одна из причин заключается в том, что в нашем опыте некоторые компиляторы (например, MSVC) не могут выполнять оптимизацию пустого базового класса, что имеет решающее значение для наших типов фиксированного размера.
Основные классы
Эти классы вам необходимо знать, если вы хотите писать функции, которые принимают или возвращают объекты Eigen.
-
Matrix означает простую плотную матрицу. Если
mявляетсяMatrix, то, например,m+mбольше не являетсяMatrix, а является «выражением матрицы». -
MatrixBase означает плотное выражение матрицы. Это означает, что
MatrixBase— это нечто, что можно складывать, умножать матрично, разлагать LU, разлагать QR... Все классы выражений матриц, включаяMatrix, наследуютMatrixBase. -
Array означает простую плотную матрицу. Если
xявляетсяArray, то, например,x+xбольше не являетсяArray, а является «выражением массива». -
ArrayBase означает плотное выражение массива. Это означает, что
ArrayBase— это нечто, что можно складывать, умножать покомпонентно и к которому можно применять различные операции над массивами... Все классы выражений массивов, включаяArray, наследуютArrayBase. -
DenseBase означает плотное (матричное или массивно) выражение. И
ArrayBaseиMatrixBaseнаследуютDenseBase.DenseBase— это место, где находятся все методы, применяемые к плотным выражениям независимо от того, являются ли они выражениями матриц или массивов. Например, методы block(...) находятся вDenseBase.
Базовые классы
Эти классы служат базовыми классами для пяти основных классов, упомянутых выше. Они более внутренние и поэтому менее интересны для пользователей библиотеки Eigen.
-
PlainObjectBase означает плотную (матрицу или массив) простую сущность, т. е. нечто, что хранит свой собственный плотный массив коэффициентов. Здесь, например, находятся методы resize() .
PlainObjectBaseнаследуетсяMatrixиArray. Но выше мы сказали, чтоMatrixнаследуется отMatrixBaseиArrayнаследуется отArrayBase. Значит ли это множественное наследование? Нет, потому чтоPlainObjectBaseсамо по себе наследуется отMatrixBaseилиArrayBaseв зависимости от того, в случае матриц или массивов. Когда мы выше сказали, чтоMatrixнаследуется отMatrixBase, мы упустили, что он наследуется косвенно черезPlainObjectBase. То же самое дляArray. - DenseCoeffsBase означает, что есть доступ к плотным коэффициентам. Это базовый класс для
DenseBase. Причина существованияDenseCoeffsBaseв том, что набор доступных коэффициентов сильно отличается в зависимости от того, имеет ли плотное выражение прямой доступ к памяти или нет (флагDirectAccessBit). Например, еслиx— обычная матрица, то уxесть прямой доступ, а уx.transpose()иx.block(...)тоже есть прямой доступ, потому что их коэффициенты можно прочитать непосредственно из памяти, но, например, уx+xнет прямого доступа к памяти, потому что для получения любого из его коэффициентов требуется вычисление (сложение), его нельзя просто прочитать из памяти. -
EigenBase означает всё, что можно оценить в простую плотную матрицу или массив (даже если это плохая идея).
EigenBase— это действительно абсолютный базовый класс для всего, что хоть как-то похоже на матрицу или массив. Это базовый класс дляDenseCoeffsBase, поэтому он находится под всей нашей иерархией плотных классов, но не ограничен только плотными выражениями. Например,EigenBaseтакже наследуется диагональными матрицами, разреженными матрицами и т. д...
Диаграммы наследования
Диаграмма наследования для Matrix выглядит следующим образом:
EigenBase<Matrix> <-- DenseCoeffsBase<Matrix> (direct access case) <-- DenseBase<Matrix> <-- MatrixBase<Matrix> <-- PlainObjectBase<Matrix> (matrix case) <-- Matrix
Диаграмма наследования для Array выглядит следующим образом:
EigenBase<Array> <-- DenseCoeffsBase<Array> (direct access case) <-- DenseBase<Array> <-- ArrayBase<Array> <-- PlainObjectBase<Array> (array case) <-- Array
Диаграмма наследования для другого класса выражения матриц, обозначенного здесь как SomeMatrixXpr, выглядит следующим образом:
EigenBase<SomeMatrixXpr> <-- DenseCoeffsBase<SomeMatrixXpr> (direct access or no direct access case) <-- DenseBase<SomeMatrixXpr> <-- MatrixBase<SomeMatrixXpr> <-- SomeMatrixXpr
Диаграмма наследования для другого класса выражения массивов, обозначенного здесь как SomeArrayXpr, выглядит следующим образом:
EigenBase<SomeArrayXpr> <-- DenseCoeffsBase<SomeArrayXpr> (direct access or no direct access case) <-- DenseBase<SomeArrayXpr> <-- ArrayBase<SomeArrayXpr> <-- SomeArrayXpr
Наконец, рассмотрим пример чего-то, что не является плотным выражением, например, диагональной матрицы. Соответствующая диаграмма наследования:
EigenBase<DiagonalMatrix> <-- DiagonalBase<DiagonalMatrix> <-- DiagonalMatrix
© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/TopicClassHierarchy.html