Implementación de Matrix OOP utilizando C ++ 11 y C ++ 14 -- ++ campo con beginner campo con object-oriented campo con c++11 campo con matrix camp codereview Relacionados El problema

Matrix OOP implementation using C++11 and C++14


1
vote

problema

Español

Sé que otras personas ya hicieron lo mismo ya, Pero estoy aprendiendo C ++ (C ++ 11/14) que viene de C (estoy leyendo la programación: Principios y práctica usando C ++, por Bjarne Strougstrup), y esta es mi oop Implementación de una matriz (N por M tamaño).

Por el momento no usa la plantilla para los tipos genéricos y usa el doble, y todo lo que hace es representar una matrix , pero aún no implementa ningún miembro de la función de cálculo. Estoy usando el Idioma de C ++ pimpl (usando el código 9988776655544330 99887776555443331 ), y el subíndice [] Operador Sobrecarga.

Me gustaría saber si estoy usando un buen patrón de programación (o un mal antipatter) y en la forma correcta de C ++ de hacer las cosas (Ej. Estructura del programa, archivos y organización, tipos, etc.). Por favor, si puede mantenerlo simple, ya que todavía falta partes del idioma que aún no he aprendido.

archivo main.cpp:

  #include <iostream> #include <memory>  #include "Matrix.hpp"  using namespace std; using namespace zgt;  constexpr size_t num_elements{ 3};  /*  Outputs:  1, 2, 3  4, 5, 6  7, 8, 9  */ int main() {     Matrix m{ num_elements }; // Squared matrix      double inc{ 1 };     for (size_t i{ 0 }; i < num_elements; i++) {         for (size_t j{ 0 }; j < num_elements; j++) {             m[i][j] = inc++;         }     }      for (size_t i{ 0 }; i < num_elements; i++) {         for (size_t j{ 0 }; j < num_elements; j++) {             if (j == 0) {                 cout << m[i][j];             } else {                 cout << ", " << m[i][j];             }         }          cout << endl;     }      return 0; }   

Archivo MATRIX.CPP:

  #include "Matrix.hpp"  using namespace std; using namespace zgt;  struct Matrix::_impl {     unique_ptr<unique_ptr<MatrixRow>[]> _m;      _impl(size_t rows, size_t cols): _m(make_unique<unique_ptr<MatrixRow>[]>(rows)) {         for (size_t i{ 0 }; i < cols; i++) {             _m[i] = make_unique<MatrixRow>(cols);         }     } };  MatrixRow& Matrix::operator[](size_t index) {     return *(pimpl->_m[index]); }  Matrix::Matrix(size_t rows, size_t cols) : pimpl(make_unique<_impl>(rows, cols)) {} Matrix::Matrix(size_t size) : Matrix::Matrix(size, size) {} Matrix::~Matrix() = default;   

Archivo MATRIX.HPP:

  #ifndef Matrix_hpp #define Matrix_hpp  #include <iostream> #include <memory>  #include "MatrixRow.hpp"  namespace zgt {     class Matrix{         struct _impl;         std::unique_ptr<_impl> pimpl;     public:         Matrix(size_t rows, size_t cols);         Matrix(size_t size); // [size][size]         ~Matrix();          MatrixRow& operator[](size_t index);     }; }  #endif   

archivo matrixrow.cpp

  #include "MatrixRow.hpp"  using namespace std; using namespace zgt;  struct MatrixRow::_impl {     unique_ptr<double[]> _v;      _impl(size_t cols): _v(make_unique<double[]>(cols)) {} };  double& MatrixRow::operator[](size_t index) {     return pimpl->_v[index]; }  MatrixRow::MatrixRow(size_t cols) : pimpl(make_unique<_impl>(cols)) {} MatrixRow::~MatrixRow() = default;   

Archivo MATRIXROW.HPP:

  #ifndef MatrixRow_hpp #define MatrixRow_hpp  #include <iostream> #include <memory>  namespace zgt {     class MatrixRow{         struct _impl;         std::unique_ptr<_impl> pimpl;     public:         MatrixRow(size_t cols);         ~MatrixRow();          double& operator[](size_t index);     }; }  #endif   
Original en ingles

I know that other people already did the same already, but I'm learning C++ (C++11/14) coming from C (I'm reading Programming: Principles and Practice Using C++, by Bjarne Stroustrup), and this is my OOP implementation of a matrix (N by M size).

At the moment it doesn't use template for generic types and uses double, and all it does is represent a matrix, but doesn't implement any calculation function members yet. I'm using the C++ PIMPL idiom (using C++11's unique_ptr and C++14's make_unique), and the subscript [] operator overload.

I'd like to know if I'm using a good programming pattern (or a bad antipattern) and in the correct C++ way of doing things (ex. program structure, files and organization, types etc...). Please if you can keep it simple, as I'm still missing parts of the language I haven't learned yet.

File main.cpp:

#include <iostream> #include <memory>  #include "Matrix.hpp"  using namespace std; using namespace zgt;  constexpr size_t num_elements{ 3};  /*  Outputs:  1, 2, 3  4, 5, 6  7, 8, 9  */ int main() {     Matrix m{ num_elements }; // Squared matrix      double inc{ 1 };     for (size_t i{ 0 }; i < num_elements; i++) {         for (size_t j{ 0 }; j < num_elements; j++) {             m[i][j] = inc++;         }     }      for (size_t i{ 0 }; i < num_elements; i++) {         for (size_t j{ 0 }; j < num_elements; j++) {             if (j == 0) {                 cout << m[i][j];             } else {                 cout << ", " << m[i][j];             }         }          cout << endl;     }      return 0; } 

File Matrix.cpp:

#include "Matrix.hpp"  using namespace std; using namespace zgt;  struct Matrix::_impl {     unique_ptr<unique_ptr<MatrixRow>[]> _m;      _impl(size_t rows, size_t cols): _m(make_unique<unique_ptr<MatrixRow>[]>(rows)) {         for (size_t i{ 0 }; i < cols; i++) {             _m[i] = make_unique<MatrixRow>(cols);         }     } };  MatrixRow& Matrix::operator[](size_t index) {     return *(pimpl->_m[index]); }  Matrix::Matrix(size_t rows, size_t cols) : pimpl(make_unique<_impl>(rows, cols)) {} Matrix::Matrix(size_t size) : Matrix::Matrix(size, size) {} Matrix::~Matrix() = default; 

File Matrix.hpp:

#ifndef Matrix_hpp #define Matrix_hpp  #include <iostream> #include <memory>  #include "MatrixRow.hpp"  namespace zgt {     class Matrix{         struct _impl;         std::unique_ptr<_impl> pimpl;     public:         Matrix(size_t rows, size_t cols);         Matrix(size_t size); // [size][size]         ~Matrix();          MatrixRow& operator[](size_t index);     }; }  #endif 

File MatrixRow.cpp

#include "MatrixRow.hpp"  using namespace std; using namespace zgt;  struct MatrixRow::_impl {     unique_ptr<double[]> _v;      _impl(size_t cols): _v(make_unique<double[]>(cols)) {} };  double& MatrixRow::operator[](size_t index) {     return pimpl->_v[index]; }  MatrixRow::MatrixRow(size_t cols) : pimpl(make_unique<_impl>(cols)) {} MatrixRow::~MatrixRow() = default; 

File MatrixRow.hpp:

#ifndef MatrixRow_hpp #define MatrixRow_hpp  #include <iostream> #include <memory>  namespace zgt {     class MatrixRow{         struct _impl;         std::unique_ptr<_impl> pimpl;     public:         MatrixRow(size_t cols);         ~MatrixRow();          double& operator[](size_t index);     }; }  #endif 
              
       
       

Lista de respuestas

3
 
vote

Partimos desde el uso:

  • No es posible escribir bucles de rango con la versión actual

  • No FilterInfo3 y FilterInfo4 (o cualquier cosa similar). Por lo que no es posible atravesar la matriz

  • FilterInfo5 no funciona en FilterInfo6 Objetos, ya que no hay FilterInfo7 .

claridad y limpieza:

  • nuke pimpl. En serio, no agrega mucho beneficio aquí. De hecho, la compilación podría aumentarse con PIMPL, ya que Matrix es muy ligero de todos modos.

  • FilterInfo8 El encabezado no es necesario, debe eliminarse.

  • doble indirección. FilterInfo9 debe ser Operation0 . Pero si PIMPL se va a nuked, se incrustará en la propia matriz.

  • Operation1 FIT AQUÍ MEJOR AQUÍ.

    nitpicks:

  • Destructor se genera automáticamente. Operation2 ING es redundante.

Algunas directrices generales:

  • OOP se mezcla generalmente con alguna programación funcional en C ++. Por ejemplo, plantillas.

  • El código de C ++ generalmente intenta proporcionar algún comportamiento predeterminado que es correcto y seguro, y algunos accidentes a la implementación subyacente que cuando se accede al programador deja a programar todo el control para sí mismo (literalmente todo).

    < / li>

Recomendación para la próxima iteración:

Creo que Operation3 será el mejor ajuste aquí. Cálculo del índice para saltar debe ser bastante fácil (es lo que hace el compilador para nosotros de todos modos). Creo que estará bien devolver Operation4 de Operation5 , porque los usuarios saben que no deben meterse con él, pero hacer que una estructura pequeña también sea buena. Algo como Operation6 sería bueno (aunque parece que no está en el estándar aún, incluso en C ++ 17). Además, obtienes iteradores gratis con enfoque vectorial.

solo escribe:

  Operation7  

Como resultado, también obtiene un bucle de rango de forma gratuita.

 

Lets start from the usage:

  • It is not possible to write range loops with the current version

  • no rowcount() and columncount() (or anything similar). So it is not possible to actually traverse matrix

  • operator[]() won't work on const objects, since there is no operator[](std::size_t index) const.

Clarity and cleanliness:

  • nuke pimpl. I'm serious, it doesn't add much benefit here. In fact, the compilation might be increased by pimpl, since matrix is very lightweight anyway.

  • #include <iostream> header is not needed, should be removed.

  • double indirection. _impl should actually be MatrixRow. But if pimpl is gonna get nuked, it will be embedded into matrix itself.

  • std::vector<> would be much better fit here.

    Nitpicks:

  • destructor is generated for you automatically. defaulting it is redundant.

Some general guidelines:

  • OOP is usually mixed with some functional programming in C++. For example, templates.

  • C++ code usually tries to provide some default behavior that is correct and safe, and some access to underlying implementation that when accessed lets programmer to take all of the control to himself (literally everything).

Recommendation for next iteration:

I think that std::vector<T> will be the best fit here. Calculating the index to jump at should be pretty easy (it is what compiler does for us anyway). I think it will be okay to return T* from operator[](), because users know they shouldn't mess with it, but making some small struct would good as well. Something like std::array_view<T> would be nice (though it seems like it is not in the standard yet, even in C++17). Also, you get iterators for free with vector approach.

Just write:

auto begin() {     return storage.begin(); }  auto end() {     return storage.end(); } 

As a result, you get range loop for free as well.

 
 

Relacionados problema

2  Hackerank - Queens Attack II - Java  ( Hackerrank queens attack ii java ) 
La definición del problema ya se puede encontrar aquí . Dado un tablero de ajedrez con dimensiones N Ã- N (donde n es de hasta 100000) y el ( r , C )...

0  Código de número de rutas posible de la longitud dada entre 2 nodos dados  ( Code for number of routes possible of the given length between 2 given nodes ) 
Recientemente me encontré en este problema , aquí hay un extracto de eso, Es bien sabido que el algoritmo de enrutamiento utilizado en Internet es altam...

2  La matriz hash realiza la eliminación gaussiana  ( Hash matrix performs gaussian elimination ) 
Esta es la matriz de hash que usé para procesar la matriz para mi algoritmo cuadrático de tamiz. Puede encontrar el código completo en aquí (es java 7 ), p...

4  Asignación de matrices para la modificación en el lugar  ( Allocating matrices for in place modification ) 
Este código parece estar funcionando. Estoy asignando matrices en la pila y los pasa a funciones para modificar en su lugar. ¿Es esta una práctica estándar, o...

19  Clase de matriz en C #  ( Matrix class in c ) 
He estado aprendiendo C # durante mi tiempo libre en los últimos meses; Antes de eso, en su mayoría estaba escribiendo Java, por lo que la transición no ha si...

3  Solución más rápida para la resta sabia de la matriz  ( Faster solution for row wise matrix subtraction ) 
Tengo 2 matrices. Tengo que calcular la distancia euclidiana entre cada fila de Matrix A y cada fila de Matrix B. En la primera solución i bucle sobre las f...

4  Aumentar el rendimiento de una matrícula de la multiplicación de matriz de 2x2  ( Increase performance of a spate of 2x2 matrix multiplication ) 
Me gustaría mejorar el rendimiento de la pieza de código a continuación (en Fortran). Da buenos resultados, pero el perfil le dice que es donde pasa la mayor ...

1  Integración de oscilador de fase perturbada  ( Perturbed phase oscillator integration ) 
Estoy integrando un sistema de osciladores de fase perturbados. Defino el sistema de ecuación y también la matriz jacobiana. Tengo que remodelar el vector dim...

5  Multiplicación de matriz y producto de punto  ( Matrix multiplication and dot product ) 
Ejercicio 2.37. Supongamos que representamos vectores v = (vi) como secuencias de números, y matrices m = (MIJ) como secuencias de vectores (las filas ...

3  Análisis de simetría para arreglos atómicos en un cristal  ( Symmetry analysis for atom arrangements in a crystal ) 
Por un tiempo ahora he tenido la intención de publicar un poco de mi código Haskell aquí para que alguien pueda decirme qué partes de la biblioteca de idiomas...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos