C++ - Problema con operador delete

Iniciado por xaps, 13 Diciembre 2013, 18:50 PM

0 Miembros y 1 Visitante están viendo este tema.

xaps

Cita de: amchacon en 14 Diciembre 2013, 17:33 PM
A ver, tu tenías definido el operador = para que devolviese un nuevo objeto matriz.

Como has hecho return *this esa matriz era una copia de this. Para hacer copias de un objeto se llama al constructor copia.

Si no has definido el constructor copia, el compilador crea uno por ti. El problema esque el compilador hace la copia literal. Lo que implica que se copian los punteros de la matriz tal cual.

Cuando esa matriz "copia" desaparece, se llama al destructor y se libera la memoria. Cuando la matriz "original" desaparece, se vuelve a llamar al destructor y se libera la misma memoria (¡Los punteros son iguales!). De ahí la excepción en tiempo de ejcución.

Aunque el error se solucionaría poniendo Matriz& en el retorno del operador =, no puedes dejarlo así porque ya sabes que las copias te van a fallar. Asi que te he rehecho el constructor copia (y para no copy&pastear el código, me he aprovechado del operador de asignación que hemos definido).

PD: Ya que estoy, los demás operadores (+ - *) también debería devolver Matriz& en vez de Matriz. De lo contrario estarás haciendo copias al montón :silbar:

Vale, el porqué del constructor copia lo he entendido. Pero cuando tu retornas Matriz&, estás retornando una dirección de memoria de una matriz que al terminar la función será eliminada si no me equivoco, además de que el objeto al que se le hace la asignación debería ser un puntero, ¿no?. En cambio, si retornas una copia, asignas la copia a la matriz correspondiente y luego la copia se elimina, ¿cierto?
"The programmers of tomorrow are the wizards of the future" - Gave Newel

amchacon

Cita de: xaps en 14 Diciembre 2013, 20:01 PM
Vale, el porqué del constructor copia lo he entendido. Pero cuando tu retornas Matriz&, estás retornando una dirección de memoria de una matriz que al terminar la función será eliminada si no me equivoco
No, estoy retornando una referencia. En este caso la referencia es this, asi que estoy retornando una referencia al propio objeto.

Eso te permite poner varios = consecutivos, cada uno coge la referencia del anterior ;)

PD: Si no usas la referencia no pasa nada, no es como si estuvieses creando un objeto ni nada parecido.

Cita de: xaps en 14 Diciembre 2013, 20:01 PMademás de que el objeto al que se le hace la asignación debería ser un puntero, ¿no?. ]En cambio, si retornas una copia, asignas la copia a la matriz correspondiente y luego la copia se elimina, ¿cierto?
¿A que te refieres? No te sigo...
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

xaps

Cita de: amchacon en 14 Diciembre 2013, 20:13 PM
No, estoy retornando una referencia. En este caso la referencia es this, asi que estoy retornando una referencia al propio objeto.

Eso te permite poner varios = consecutivos, cada uno coge la referencia del anterior ;)

PD: Si no usas la referencia no pasa nada, no es como si estuvieses creando un objeto ni nada parecido.
¿A que te refieres? No te sigo...

Vale, creo que ya lo tengo. Por lo visto, no había entendido bien que era realmente la referencia.

Cita de: xaps en 14 Diciembre 2013, 20:01 PM
Pero cuando tu retornas Matriz&, estás retornando una dirección de memoria de una matriz que al terminar la función será eliminada si no me equivoco, además de que el objeto al que se le hace la asignación debería ser un puntero, ¿no?.
La parte de que estoy hablando de punteros olvídala, era un fallo de concepto mio.
El resto sería algo como esto:
Citar
Si una función retorna una referencia, ha de tener el mismo cuidado que si la función retornara un puntero. La referencia que se devuelva debe estar ligada a algo que no sea liberado cuando la función retorne. Si no, la referencia se referirá a un trozo de memoria sobre el que ya no tiene control.
http://arco.esi.uclm.es/~david.villa/pensar_en_C++/vol1/ch11s02.html

Por lo que entiendo que en la sobrecarga del operador = sí que se pueda retornar una referencia, ya que trabaja sobre uno de sus parámetros (el implícito). Pero no entiendo porqué debería hacerlo con las sobrecargas de los operadores + - y *, ya que la matriz resultado es una matriz generada dentro de la función, por lo que a la que salga de la función ésta será eliminada y cualquier referencia a ella contendrá datos basura, ¿no?. No se si me explico bien... :S

Gracias por estar resolviéndome estas dudas ^^
"The programmers of tomorrow are the wizards of the future" - Gave Newel

amchacon

Vale fallo mío, creía que el operador + era para sumar la misma matriz. Pero por lo que veo genera otra matriz nueva  :silbar:

Para eso te recomiendo que uses una función, un operador se supone que es para hacer una operación en un objeto (no para generar otros).
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

xaps

Cita de: amchacon en 15 Diciembre 2013, 17:55 PM
Vale fallo mío, creía que el operador + era para sumar la misma matriz. Pero por lo que veo genera otra matriz nueva  :silbar:

Para eso te recomiendo que uses una función, un operador se supone que es para hacer una operación en un objeto (no para generar otros).

Lo hago más que nada para poder realizar operaciones del tipo:
Matriz m1, m2, m3, m4;
m1 = m2 + m3 + m4;


Es decir, como si fuera un entero o cualquier otro tipo. Pero gracias por la recomendación ^^

Al final he conseguido arreglar la función borrar() a modo de prueba y error, y he averiguado varias cosas:
- Cuando haces delete a un puntero, éste se queda apuntando a la dirección de memoria que lo hacia antes y no pasa a valer NULL.
- La contructora-copiadora que me has pasado tenia un pequeño fallo que me ha hecho pasarme, literalmente, horas a base de prueba y error hasta ver que era lo que estaba ocurriendo (que no te lo estoy echando en cara, todo lo contrario, me ha ayudado a comprender mejor el funcionamiento de POO y te estoy agradecido ^^). Al ser una constructora, había que inicializar el puntero matr a NULL porque si no, cuando hagamos la asignación dentro de la constructora, en la función borrar intentará eliminar unas posiciones de memoria que no son propias del programa, ya que la condición if (this->matr != NULL) la pasaba.

Seguramente me deje alguna cosilla más que quería comentar, si me acuerdo de algo nuevo editaré este comentario ^^ Os adjunto el código de la clase (funciona como mínimo para multiplicar y asignar, falta ver el resto de funciones):

Código (cpp) [Seleccionar]

#include <iostream>
#include <vector>

using namespace std;

class Matriz {

private:
 
 int nfilas;
 int ncolumnas;
 int **matr;
 
 void borrar();

public:

 //Constructoras
 Matriz();
 Matriz(int filas, int columnas);
 
 //Constructora-copiadora
 Matriz(const Matriz& m);
 
 //Destructora
 ~Matriz();
 
 //Consultoras
 int filas() const;
 int columnas() const;
 int consultar(int fila, int columna) const;
 
 //Modificadora
 void modificar(int fila, int columna, int x);
 
 //Entrada / Sortida
 void leer();
 void escribir() const;
 
 //Operadores
 Matriz& operator =(const Matriz &b);
 
 Matriz operator +(const Matriz &b) const;
 Matriz operator -(const Matriz &b) const;
 Matriz operator *(const Matriz &b) const;
 
 bool operator ==(const Matriz &mat) const;
 bool operator !=(const Matriz &mat) const;
};

Matriz::Matriz()
{
 nfilas = 0;
 ncolumnas = 0;
 matr = NULL;
}

Matriz::Matriz(int filas, int columnas)
{
 this->nfilas = filas;
 this->ncolumnas = columnas;
 
 if (nfilas > 0 and ncolumnas > 0)
 {
   matr = new int* [filas];
   for (int i = 0; i < filas; ++i)
   {
     matr[i] = new int [columnas];
   }
 }
 else
 {
   nfilas = 0;
   ncolumnas = 0;
   matr = NULL;
 }
}

Matriz::Matriz(const Matriz &m)
{
 this->matr = NULL;
 *this = m;
}

Matriz::~Matriz() { borrar(); }

void Matriz::borrar()
{
 if (this->matr != NULL)
 {
   for (int i = 0; i < nfilas; ++i) delete[] matr[i];
   delete[] matr;
   matr = NULL;
 }
}

int Matriz::filas() const { return nfilas;}

int Matriz::columnas() const { return ncolumnas;}

int Matriz::consultar(int fila, int columna) const { return matr[fila][columna];}

void Matriz::modificar(int fila, int columna, int x) { matr[fila][columna] = x;}

void Matriz::leer()
{
 for (int i = 0; i < nfilas; ++i)
   for (int j = 0; j < ncolumnas; ++j) cin >> matr[i][j];
}

void Matriz::escribir() const
{
 for (int i = 0; i < nfilas; ++i)
 {
   for (int j = 0; j < ncolumnas; ++j) cout << matr[i][j] << " ";
   cout << endl;
 }
}

Matriz& Matriz::operator =(const Matriz &mat)
{
 if (this != &mat)
 {
   this->borrar();

   if (mat.matr)
   {
     this->nfilas = mat.nfilas;
     this->ncolumnas = mat.ncolumnas;
     
     this->matr = new int* [nfilas];
     for (int i = 0; i < nfilas; ++i)
this->matr[i] = new int [ncolumnas];
     
     for (int i = 0; i < nfilas; ++i)
     {
for (int j = 0; j < ncolumnas; ++j)
 this->matr[i][j] = mat.matr[i][j];
     }
   }
 }
 return *this;
}

Matriz Matriz::operator +(const Matriz &b) const
{
 int filas = this->nfilas;
 int columnas = this->ncolumnas;
 
 Matriz res(filas, columnas);
 
 for (int i = 0; i < filas; ++i)
   for (int j = 0; j < columnas; ++j)
     res.matr[i][j] = this->matr[i][j] + b.matr[i][j];
   
 return res;
}

Matriz Matriz::operator -(const Matriz &b) const
{
 int filas = this->nfilas;
 int columnas = this->ncolumnas;
 
 Matriz res(filas, columnas);
 
 for (int i = 0; i < filas; ++i)
   for (int j = 0; j < columnas; ++j)
     res.matr[i][j] = this->matr[i][j] - b.matr[i][j];
   
 return res;
}

Matriz Matriz::operator *(const Matriz &b) const
{
 if (this->ncolumnas == b.nfilas)
 {
   int pos = this->ncolumnas;
   int filas = this->nfilas;
   int columnas = b.ncolumnas;
   
   Matriz res(filas, columnas);
   for (int i = 0; i < filas; ++i)
   {
     for (int j = 0; j < columnas; ++j)
     {
int value = 0;
for (int k = 0; k < pos; ++k) value += this->matr[i][k] * b.matr[k][j];
res.matr[i][j] = value;
     }
   };
   return res;
 }
}

bool Matriz::operator ==(const Matriz &mat) const
{
 for (int i = 0; i < nfilas; ++i)
   for (int j = 0; j < ncolumnas; ++j)
     if (this->matr[i][j] != mat.matr[i][j]) return false;
 
 return true;
}

bool Matriz::operator !=(const Matriz &mat) const
{
 for (int i = 0; i < nfilas; ++i)
   for (int j = 0; j < ncolumnas; ++j)
     if (this->matr[i][j] != mat.matr[i][j]) return true;
 
 return false;
}


Cualquier nueva duda que tenga la haré desde este mismo tema (modificando el título) para no crear nuevos temas innecesarios y no se repita la información.
Si veis algún cambio raro en el código que no haya comentado y que no se entienda comentarlo y os lo explicaré encantado.

Saludos y muchas gracias amchacon.
"The programmers of tomorrow are the wizards of the future" - Gave Newel

amchacon

Cita de: xaps en 15 Diciembre 2013, 21:31 PM
Lo hago más que nada para poder realizar operaciones del tipo:
Matriz m1, m2, m3, m4;
m1 = m2 + m3 + m4;


Es decir, como si fuera un entero o cualquier otro tipo. Pero gracias por la recomendación ^^
Esa sentencia funcionaría exactamente igual con referencias, además sería muchísimo más eficiente (no tienes que estar copiando, creando nuevos objetos, borrando...).

De hecho yo me definiría y usaría el operador +=, que eso siempre va a ser más eficiente que hacer dos por separado (+ y =).

Cita de: xaps en 15 Diciembre 2013, 21:31 PMA- La contructora-copiadora que me has pasado tenia un pequeño fallo que me ha hecho pasarme, literalmente, horas a base de prueba y error hasta ver que era lo que estaba ocurriendo (que no te lo estoy echando en cara, todo lo contrario, me ha ayudado a comprender mejor el funcionamiento de POO y te estoy agradecido ^^). Al ser una constructora, había que inicializar el puntero matr a NULL porque si no, cuando hagamos la asignación dentro de la constructora, en la función borrar intentará eliminar unas posiciones de memoria que no son propias del programa, ya que la condición if (this->matr != NULL) la pasaba.
Sí bueno, yo tengo la mala suerte de atraer los errores estúpidos. Codeo demasiado rápido a veces :silbar:

En C++11 puedes inicializar una variable por defecto en una clase. De formas que no tienes que estar matr = NULL en todos los constructores xD
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

xaps

#16
Cita de: amchacon en 15 Diciembre 2013, 22:08 PM
Esa sentencia funcionaría exactamente igual con referencias, además sería muchísimo más eficiente (no tienes que estar copiando, creando nuevos objetos, borrando...).
Pero si lo hiciera por referencias estaría modificado las matrices que estoy sumando, ¿no?

Cita de: amchacon en 15 Diciembre 2013, 22:08 PM
De hecho yo me definiría y usaría el operador +=, que eso siempre va a ser más eficiente que hacer dos por separado (+ y =).
La verdad, no se me había ocurrido, pero me parece buena idea añadirlo, además de que tengo pendiente sobrecargar los operadores << y >> de iostream para la entrada/salida de datos. También pensé en los operadores ++ y --, pero no les veo utilidad para matrices.

Cita de: amchacon en 15 Diciembre 2013, 22:08 PM
En C++11 puedes inicializar una variable por defecto en una clase. De formas que no tienes que estar matr = NULL en todos los constructores xD
Voy a investigar sobre esto, parece bastante interesante. Muchas gracias ^^

EDITO: He modificado la constructora añadiendo los valores por defecto y gracias a esto he conseguido ahorrarme la constructora que tenía sin parámetros ^^ Aquí el código:

Código (cpp) [Seleccionar]

Matriz::Matriz(int filas = 0, int columnas = 0) : nfilas(filas), ncolumnas(columnas)
{
 if (nfilas > 0 and ncolumnas > 0)
 {
   matr = new int* [filas];
   for (int i = 0; i < filas; ++i)
   {
     matr[i] = new int [columnas];
   }
 }
 else matr = NULL;
}


También he modificado la constructora para que modifique los parámetros de la clase antes del propio código. Según he leído, esto sirve para inicializar objetos de otras clases usando sus constructores y no los por defecto, pero ésto no se podía hacer de otra manera también? Es decir, ¿estos dos códigos no harían lo mismo?

Código (cpp) [Seleccionar]

Clase1::Clase1(Clase2 obj) : parametro1(clase2) {}

Código (cpp) [Seleccionar]

Clase1::Clase1(Clase2 obj)
{
 parametro1 = Clase1 (obj);
}


Gracias! ^^
"The programmers of tomorrow are the wizards of the future" - Gave Newel

amchacon

Cita de: xaps en 16 Diciembre 2013, 01:49 AM
Pero si lo hiciera por referencias estaría modificado las matrices que estoy sumando, ¿no?
Es verdad, no había caído en eso.

Aunque solo modificarías la primera.

Cita de: xaps en 16 Diciembre 2013, 01:49 AMVoy a investigar sobre esto, parece bastante interesante. Muchas gracias ^^

EDITO: He modificado la constructora añadiendo los valores por defecto y gracias a esto he conseguido ahorrarme la constructora que tenía sin parámetros ^^ Aquí el código:

Código (cpp) [Seleccionar]

Matriz::Matriz(int filas = 0, int columnas = 0) : nfilas(filas), ncolumnas(columnas)
{
 if (nfilas > 0 and ncolumnas > 0)
 {
   matr = new int* [filas];
   for (int i = 0; i < filas; ++i)
   {
     matr[i] = new int [columnas];
   }
 }
 else matr = NULL;
}


También he modificado la constructora para que modifique los parámetros de la clase antes del propio código. Según he leído, esto sirve para inicializar objetos de otras clases usando sus constructores y no los por defecto, pero ésto no se podía hacer de otra manera también? Es decir, ¿estos dos códigos no harían lo mismo?

Código (cpp) [Seleccionar]

Clase1::Clase1(Clase2 obj) : parametro1(clase2) {}

Código (cpp) [Seleccionar]

Clase1::Clase1(Clase2 obj)
{
 parametro1 = Clase1 (obj);
}


Gracias! ^^
En realidad no me refería a eso (para eso no hace falta recurrir a C++11). Yo me refería a:

Código (cpp) [Seleccionar]
class Matriz
{
 int ** matr = NULL;
 //...
}


Como ves, lo que inicializo es el mismo atributo de la clase. Así no tengo que ponerlo en todos los constructores.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

xaps

Cita de: amchacon en 16 Diciembre 2013, 09:32 AM
Es verdad, no había caído en eso.

Aunque solo modificarías la primera.
En realidad no me refería a eso (para eso no hace falta recurrir a C++11). Yo me refería a:

Código (cpp) [Seleccionar]
class Matriz
{
 int ** matr = NULL;
 //...
}


Como ves, lo que inicializo es el mismo atributo de la clase. Así no tengo que ponerlo en todos los constructores.

Vaya, creía que te referías a lo otro que había añadido... Creo que he querido ir demasiado rápido al implementarlo y he lo he hecho con lo primero que he encontrado  :silbar: Aunque tampoco me ha ido mal ^^

Pero bueno, me ha parecido buena idea también y lo he incorporado a la clase, aunque solo lo he hecho con el parámetro matr, ya que he considerado mejor que los otros dos parámetros los deje por defecto en el constructor y que se asignen a la vez que se crea una nueva instancia del objeto.

Esta vez he hecho bastantes más cambios. He añadido los operadores +=, -=, >>(istream) y << (ostream), por lo que he eliminado las funciones leer() y escribir().  También he añadido el producto de una matriz por un escalar y he intentado simular la propiedad de conmutatividad, aunque no se si lo he hecho de la forma correcta. También he cambiado la mayoría de sobrecargas y las he hecho amigas de la clase, de manera que sean externas y no usen el parámetro implícito, ya que me parecía un poco feo utilizar solo el parámetro implícito como consulta pudiendo poner las funciones como amigas de la clase. También he arreglado un par de cosas que podían hacer petar el programa y he probado todas las funciones un poco por encima.

Aquí el código de la clase y del programa que estoy usando para hacer las pruebas:

Matriz.h:
Código (cpp) [Seleccionar]
#include <iostream>

using namespace std;

class Matriz {

private:
 
  int nfilas;
  int ncolumnas;
  int **matr = NULL;
 
  void borrar();

public:

  //Constructora
  Matriz(int filas, int columnas);
 
  //Constructora-copiadora
  Matriz(const Matriz& m);
 
  //Destructora
  ~Matriz();
 
  //Consultoras
  int filas() const;
  int columnas() const;
  int consultar(int fila, int columna) const;
 
  //Modificadora
  void modificar(int fila, int columna, int x);
 
  //Operadores
  Matriz& operator =(const Matriz &b);
 
  void operator +=(const Matriz &mat);
  void operator -=(const Matriz &mat);
 
  friend Matriz operator +(const Matriz &a, const Matriz &b);
  friend Matriz operator -(const Matriz &a, const Matriz &b);
  friend Matriz operator *(const Matriz &a, const Matriz &b);
  friend Matriz operator *(const Matriz &a, int b);
  friend Matriz operator *(int a, const Matriz &b);
 
  friend bool operator ==(const Matriz &a, const Matriz &b);
  friend bool operator !=(const Matriz &a, const Matriz &b);
 
  friend ostream& operator <<(ostream &salida, const Matriz &mat);
  friend istream& operator >>(istream &entrada, Matriz &mat);
};

Matriz::Matriz(int filas = 0, int columnas = 0) : nfilas(filas), ncolumnas(columnas)
{
  if (nfilas > 0 and ncolumnas > 0)
  {
    matr = new int* [filas];
    for (int i = 0; i < filas; ++i) matr[i] = new int [columnas];
  }
}

Matriz::Matriz(const Matriz &m) { *this = m; }

Matriz::~Matriz() { borrar(); }

void Matriz::borrar()
{
  if (this->matr != NULL)
  {
    for (int i = 0; i < nfilas; ++i) delete[] matr[i];
    delete[] matr;
    matr = NULL;
  }
}

int Matriz::filas() const { return nfilas;}

int Matriz::columnas() const { return ncolumnas;}

int Matriz::consultar(int fila, int columna) const { return matr[fila][columna];}

void Matriz::modificar(int fila, int columna, int x) { matr[fila][columna] = x;}

Matriz& Matriz::operator =(const Matriz &mat)
{
  if (this != &mat)
  {
    this->borrar();

    if (mat.matr)
    {
      this->nfilas = mat.nfilas;
      this->ncolumnas = mat.ncolumnas;
     
      this->matr = new int* [nfilas];
      for (int i = 0; i < nfilas; ++i)
this->matr[i] = new int [ncolumnas];
     
      for (int i = 0; i < nfilas; ++i)
      {
for (int j = 0; j < ncolumnas; ++j)
  this->matr[i][j] = mat.matr[i][j];
      }
    }
  }
  return *this;
}

void Matriz::operator +=(const Matriz &mat)
{
  if (this->nfilas != 0 and this->ncolumnas != 0 and mat.nfilas != 0 and mat.ncolumnas != 0)
  {
    for (int i = 0; i < nfilas; ++i)
      for (int j = 0; j < ncolumnas; ++j)
this->matr[i][j] += mat.matr[i][j];
  }
}

void Matriz::operator -=(const Matriz &mat)
{
  if (this->nfilas != 0 and this->ncolumnas != 0 and mat.nfilas != 0 and mat.ncolumnas != 0)
  {
    for (int i = 0; i < nfilas; ++i)
      for (int j = 0; j < ncolumnas; ++j)
this->matr[i][j] -= mat.matr[i][j];
  }
}

Matriz operator +(const Matriz &a, const Matriz &b)
{
  int filas = a.nfilas;
  int columnas = a.ncolumnas;
 
  Matriz res(filas, columnas);
 
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j)
      res.matr[i][j] = a.matr[i][j] + b.matr[i][j];
   
  return res;
}

Matriz operator -(const Matriz &a, const Matriz &b)
{
  int filas = a.nfilas;
  int columnas = a.ncolumnas;
 
  Matriz res(filas, columnas);
 
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j)
      res.matr[i][j] = a.matr[i][j] - b.matr[i][j];
   
  return res;
}

Matriz operator *(const Matriz &a, const Matriz &b)
{
  if (a.ncolumnas == b.nfilas)
  {
    int pos = a.ncolumnas;
   
    int filas = a.nfilas;
    int columnas = b.ncolumnas;
   
    Matriz res(filas, columnas);
    for (int i = 0; i < filas; ++i)
    {
      for (int j = 0; j < columnas; ++j)
      {
int value = 0;
for (int k = 0; k < pos; ++k) value += a.matr[i][k] * b.matr[k][j];
res.matr[i][j] = value;
      }
    }
    return res;
  }
}

Matriz operator *(const Matriz &a, int b)
{
  int filas = a.nfilas;
  int columnas = a.ncolumnas;
 
  Matriz res(filas, columnas);
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j) res.matr[i][j] = a.matr[i][j] * b;
 
  return res;
}

Matriz operator *(int a, const Matriz &b) { return operator*(b, a); }

bool operator ==(const Matriz &a, const Matriz &b)
{
  if (a.nfilas != b.nfilas or a.ncolumnas != b.ncolumnas) return false;
  for (int i = 0; i < a.nfilas; ++i)
    for (int j = 0; j < a.ncolumnas; ++j)
      if (a.matr[i][j] != b.matr[i][j]) return false;
 
  return true;
}

bool operator !=(const Matriz &a, const Matriz &b)
{
  if (a.nfilas != b.nfilas or a.ncolumnas != b.ncolumnas) return true;
  for (int i = 0; i < a.nfilas; ++i)
    for (int j = 0; j < a.ncolumnas; ++j)
      if (a.matr[i][j] != b.matr[i][j]) return true;
 
  return false;
}

ostream& operator <<(ostream &salida, const Matriz &mat)
{
  for (int i = 0; i < mat.nfilas; ++i)
  {
    for (int j = 0; j < mat.ncolumnas; ++j) salida << mat.matr[i][j] << " ";
    salida << endl;
  }
  return salida;
}

istream& operator >>(istream &entrada, Matriz &mat)
{
  for (int i = 0; i < mat.nfilas; ++i)
    for (int j = 0; j < mat.ncolumnas; ++j) entrada >> mat.matr[i][j];
  return entrada;
}


test.cpp:
Código (cpp) [Seleccionar]
#include "Matriz.h"

int main()
{
  int f1, c1, f2, c2;

  cout << "Introduce el tamaño de la primera matriz:" << endl;
  cin >> f1 >> c1;
  Matriz mat1(f1, c1);
  cout << "Introduce los valores de la matriz:" << endl;
  cin >> mat1;
 
  cout << "Introduce el tamaño de la segunda matriz:" << endl;
  cin >> f2 >> c2;
  Matriz mat2(f2, c2);
  cout << "Introduce los valores de la matriz:" << endl;
  cin >> mat2;

 
  if (c1 == f2)
  {
    Matriz res;
    res = mat1 * mat2;
    cout << res << endl;
   
    res = mat1 + mat2;
    cout << res << endl;
   
    res = mat1 - mat2;
    cout << res << endl;
   
    res = res * 4;
    cout << res << endl;
   
    res = 2 * res;
    cout << res << endl;
   
    res += mat1;
    cout << res << endl;
   
    res -= mat2;
    cout << res << endl;
   
    if (res == mat1) cout << "Igualdad incorrecta" << endl;
    else cout << "Igualdad correcta" << endl;
    if (res != mat1) cout << "Desigualdad correcta" << endl;
    else cout << "Desigualdad incorrecta" << endl;
  }
}


¿Que te va pareciendo el código? ¿Crees que hay algo que mejorar o que añadirle? Tengo pensado añadir Gauss a la clase para escalonar y resolver sistemas, pero antes quiero tener la parte más básica bien hecha para luego no tener tantos problemas ^^

Gracias por la ayuda!
"The programmers of tomorrow are the wizards of the future" - Gave Newel

amchacon

Código (cpp) [Seleccionar]
bool operator ==(const Matriz &a, const Matriz &b)
{
if (a.nfilas != b.nfilas or a.ncolumnas != b.ncolumnas) return false;
for (int i = 0; i < a.nfilas; ++i)
   for (int j = 0; j < a.ncolumnas; ++j)
     if (a.matr[i][j] != b.matr[i][j]) return false;

return true;
}

bool operator !=(const Matriz &a, const Matriz &b)
{
if (a.nfilas != b.nfilas or a.ncolumnas != b.ncolumnas) return true;
for (int i = 0; i < a.nfilas; ++i)
   for (int j = 0; j < a.ncolumnas; ++j)
     if (a.matr[i][j] != b.matr[i][j]) return true;

return false;
}


Esas líneas se pueden reducir a:

Código (cpp) [Seleccionar]
bool operator ==(const Matriz &a, const Matriz &b)
{
if (a.nfilas != b.nfilas or a.ncolumnas != b.ncolumnas) return false;
for (int i = 0; i < a.nfilas; ++i)
   for (int j = 0; j < a.ncolumnas; ++j)
     if (a.matr[i][j] != b.matr[i][j]) return false;

return true;
}

bool operator !=(const Matriz &a, const Matriz &b)
{
return !(a == b);
}


Te falta por añadir los determinantes (para una matriz nxn). Y los operadores *= y /= (este ultimo con números enteros).
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar