Jump to content

Overload de Operadores


amp
 Share

Recommended Posts

Boas,

Alguém me consegue descobrir o bug neste código?

Já andei às voltas, mas ainda não consegui ver onde está o erro...

O resultado( na imagem ) da execução está totalmente errado. O problema parece-me

estar no retorno da função de overload, porque dentro da mesma todas as contas

batem certo.

Agradeço se alguém me puder ajudar 🙂

Definição da Classe Matrix

#ifndef MATRIX_H
#define MATRIX_H

#include <iostream>
using std::ostream;
using std::istream;

class Matrix
{
 friend ostream& operator<<( ostream&, const Matrix & );
 friend istream &operator>>( istream &, Matrix & );
public:
 Matrix( const int = 1, const int = 1 );
 ~Matrix();

 bool operator==( const Matrix & );
 bool operator!=( const Matrix & );

 const Matrix& operator=( const Matrix & );
 Matrix operator+( const Matrix & ) const;
 Matrix operator*( const Matrix & ) const;
 Matrix operator-( const Matrix & ) const;

 const Matrix& operator+=( const Matrix & );
 const Matrix& operator*=( const Matrix & );

 //subscript operator for non-const objects returns modifiable lvalue
 double &operator()( int, int );
 //subscript operator for const objects returns rvalue
 double operator()( int, int ) const;

 int getNumberOfColumns() const;
 int getNumberOfRows() const;

private:
 int numberOfColumns;
 int numberOfRows;
 double **ptr;
};

#endif
 

Implementação da Classe Matrix

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
using std::ios_base;
#include <iomanip>
using std::setw;
#include <cstdlib>
using std::exit;

#include "matrix.h"

Matrix::Matrix( const int rows, const int columns )
:numberOfColumns( columns ),
numberOfRows( rows )
{
 ptr = new double*[ rows ];
 for( int i = columns; i; )
 {
   i--;
   ptr[ i ] = new double[ columns ];
 }
}

Matrix::~Matrix( )
{
 for( int i = numberOfRows; i; )
   delete [] ptr[ --i ]; // release space
 delete ptr;
}


bool Matrix::operator==( const Matrix &right ) //boolean equal operator
{
 if( numberOfColumns != right.numberOfColumns || numberOfRows != right.numberOfRows )
   return false;
 for( int i = numberOfRows; i; )
 {
   i--;
   for( int j = numberOfRows; j; )
   {
     j--;
     if( ptr[ i ][ j ] != right( i, j ) )
       return false;
   }
 }

 return true;
}

bool Matrix::operator!=( const Matrix &right ) //boolean not equal operator
{
 return !( *this == right );
}


const Matrix& Matrix::operator=( const Matrix &right ) //assignement operator
{
 if( &right != this )
 {
   if( numberOfColumns!=right.numberOfColumns || numberOfRows!=right.numberOfRows )
   {
     for( int i = 0; i<numberOfRows; i++ )
       delete [] ptr[ i ]; // release space
     delete ptr;

     // resize this object
     numberOfColumns = right.numberOfColumns;
     numberOfRows = right.numberOfRows;

     // create space for array copy
     ptr = new double*[ numberOfRows ];
     for( int i = 0; i<numberOfRows; i++ )
       ptr[ i ] = new double[ numberOfColumns ];
   } // end inner if

   //Copia matriz
   for( int i = numberOfRows; i; )
     {
       i--;
       for( int j = numberOfColumns; j; )
       {
         j--;
         ptr[ i ][ j ] = right( i, j );
       }
     }
 }

 return *this;
}


Matrix Matrix::operator+( const Matrix &right ) const //addition operator
{
 if( numberOfColumns != right.numberOfColumns || numberOfRows != right.numberOfRows )
   {
     cerr << "\n*** Nao pode adicionar as duas matrizes. ***"
         << endl;
     return *this;
   }

 Matrix sum( numberOfRows, numberOfColumns );

 for( int i = numberOfRows; i; )
 {
   i--;
   for( int j = numberOfColumns; j; )
     {
       j--;
       sum( i, j ) = ( right( i, j ) + ptr[ i ][ j ]);
     }
 }

 return sum;
}

Matrix Matrix::operator*( const Matrix &right ) const//multiplication operator
{
 if( numberOfColumns != right.numberOfRows )
   {
     cerr << "\n*** Nao pode multiplicar as duas matrizes! ***\n"
         << "\t*** Dimensoes Invalidas! ***\n";
     return *this;
   }

 cout << *this << endl;
 cout << right << endl;
 Matrix prod( numberOfRows, right.numberOfColumns );

 for( int i = 0; i<numberOfRows; i++ )
 {
   for( int j = 0; j<right.numberOfColumns; j++ )
     {
       prod( i, j ) = 0;
       for( int n = 0; n<numberOfColumns; n++ )
         prod( i, j ) += ptr[ i ][ n ]*right( n, j );
       cout << prod(i,j) << " ";
     }
   cout << endl;
 }
cout << "ola" << endl << endl;

cout << prod << endl;
 return prod;
}

Matrix Matrix::operator-( const Matrix &right ) const //subtraction operator
{
 if( numberOfColumns != right.numberOfColumns || numberOfRows != right.numberOfRows )
   {
     cerr << "\n*** Nao pode adicionar duas matrizes de dimensoes diferentes! ***"
         << endl;
     return *this;
   }

 Matrix sub( numberOfRows, numberOfColumns );

 for( int i = numberOfRows; i; )
 {
   i--;
   for( int j = numberOfColumns; j; )
     {
       j--;
       sub( i, j ) = ptr[ i ][ j ] - right( i, j );
     }
 }

 return sub;
}

const Matrix& Matrix::operator+=( const Matrix &right ) //addition operator
{
 if( numberOfColumns != right.numberOfColumns || numberOfRows != right.numberOfRows )
   {
     cerr << "\n*** Nao pode adicionar as duas matrizes. ***"
         << endl;
     return *this;
   }

 for( int i = numberOfRows; i; )
 {
   i--;
   for( int j = numberOfColumns; j; )
     {
       j--;
       ptr[ i][j]= ( right( i, j ) + ptr[ i ][ j ]);
     }
 }

 return *this;
}

const Matrix& Matrix::operator*=( const Matrix &right ) //multiplication operator
{
 Matrix prod( numberOfRows, right.numberOfColumns );
 (*this) = ( (*this)*right );

 return (*this);
}


// overloaded subscript operator for non-const Matrix;
// reference return creates a modifiable lvalue
double &Matrix::operator()( int i, int j )
{
 if ( i < 0 || i >= numberOfRows  )
 {
     cerr << "\n*** Erro: Inidice " << i << " invalido ***" << endl;
     exit( 1 ); // terminate program; subscript out of range
 } // end i1f

 if ( j < 0 || j >= numberOfColumns  )
 {
     cerr << "\n*** Erro: Inidice " << j << " invalido ***" << endl;
     exit( 1 ); // terminate program; subscript out of range
 } // end if

 return ptr[ i ][ j ]; // reference return
}

// overloaded subscript operator for const Matrix
// const reference return creates an rvalue
double Matrix::operator()( int i, int j ) const
{
 // check for subscript out-of-range error
 if ( i < 0 || i >= numberOfRows  )
 {
     cerr << "\n*** Erro: Inidice " << i << " invalido ***" << endl;
     exit( 1 ); // terminate program; subscript out of range
 } // end if

 if ( j < 0 || j >= numberOfColumns  )
 {
     cerr << "\n*** Erro: Inidice " << j << " invalido ***" << endl;
     exit( 1 ); // terminate program; subscript out of range
 }

 return ptr[ i ][ j ];
}

//Devolve o numero de colunas
int Matrix::getNumberOfColumns() const
{
 return numberOfColumns;
}

//Devolve o numero de linhas
int Matrix::getNumberOfRows() const
{
 return numberOfRows;
}

ostream& operator<<( ostream& output, const Matrix & m )
{
 int i;
 ios_base::fmtflags originalFormat = output.flags();

 for( int i = 0; i<m.numberOfRows; i++ )
   {
     for( int j = 0; j< m.numberOfColumns; j++ )
       {
         output << setw( 6 ) << m.ptr[ i ][ j ] << " ";
       }
     output << endl;
   }

 output.flags( originalFormat );
 return output;
}

istream &operator>>( istream& input, Matrix & m )
{
 for( int i = 0; i<m.numberOfRows; i++ )
   for( int j = 0; j< m.numberOfColumns; j++ )
     input >> m.ptr[ i ][ j ];
}
Programa de teste
#include <iostream>
using std::cout;
using std::cin;

#include "matrix.h"


int
main()
{
 Matrix olaOla( 2, 2 );
 Matrix adeus( 2, 2);
 Matrix C( 2, 2 );

 cout << "Introduza a matriz: ";
 cin  >> olaOla;

 cout << "Introduza a segunda matriz: ";
 cin  >> adeus;

 C= adeus+olaOla;
 cout << "\nA matriz esta como:\n\n";

 cout << C;

 return 0;
}
Link to comment
Share on other sites

Ainda bem que está resolvido. O exemplo da matriz é excelente para testar a sobrecarga (ou overload) de operadores, porém cria problemas secundários (subsequentemente resolvidos com expression templates) que passo a ilustrar:

Suponhamos que temos a multiplicação de 3 matrizes (A1,A2 e A3) de dimensões nxn e finalmente um vector V1:

V4=A1*A2*A3*V1 // mmult.mvmult

Se executarmos a sequência A1*A2*A3 primeiro temos 2* O(n^3) + O(n^2)

Porém, se executarmos a sequência V2=A3*V1; V3=A2*V2; V4=A1*V3 temos 3* O(n^2)

Significa que o ideal é usar um pacote tipo LAPACK ou LINPACK que força uma certa forma de efectuar as operações. Há muito software em C++ para matrizes e álgebra linear (por exemplo o EIGEN) mas que usa expression templates.

Na minha opinião: usa o LAPACK e GOTO_BLAS e cria uma classe sem Overload. É muito mais directo, apesar de dar um pouco mais de trabalho.

P.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.