I am having a problem with overloading an operator within a class structure. Below is the program that illustrates my problem. It defines a class Matrix, creates two matrices and multiplies them.

I created to multiplication functions. The first is a straight function, the second uses the overloaded * operator. The two methods produce different results.

#include <fstream.h>

class Matrix
 {
  private:
    int ROWS, COLUMNS;
    double *M;
  public:
    Matrix() { };                                                         //default constructor
    Matrix(int R, int C){ROWS=R; COLUMNS=C; M=new double[ROWS*COLUMNS];}; //constructor
    ~Matrix() {delete[] M;};        // destructor
    int rows() {return ROWS;}
    int cols() {return COLUMNS;}
    void set(int R, int C) {ROWS=R; COLUMNS=C; M=new double[ROWS*COLUMNS];};
    void m (int R, int C, double V) {M[R*COLUMNS+C]=V;};
    double m (int R, int C) {return M[R*COLUMNS+C];};
    void dump() {for (int r=0; r<ROWS; r++) {for (int c=0; c<COLUMNS; c++)
                    cout << M[r*COLUMNS+c]<< " "; cout << endl;};};
    void dump(fstream &fout) {for (int i=0; i<(ROWS*COLUMNS); i++)
                    {fout << M[i]; if (i!=(ROWS*COLUMNS-1)) fout << ", ";};};
    Matrix operator * (Matrix &);
  };

Matrix Matrix::operator* (Matrix &B)
 {
  Matrix C;
  double ans;
  C.set(rows(), B.cols());
  for (int r=0; r<rows(); r++)
    for (int c=0; c<B.cols(); c++)
      {
       ans=0;
       for (int i=0; i<cols(); i++)
         ans=m(r,i)*B.m(i,c)+ans;
       C.m(r,c,ans);
      };
  return(C);
 };

void multiply(const Matrix &A, const Matrix &B, Matrix &C)  //This Works!! Or at least seems to
{
 double ans;
 C.set(A.rows(), B.cols());
 for (int r=0; r<A.rows(); r++)
   for (int c=0; c<B.cols(); c++)
     {
      ans=0;
      for (int i=0; i<A.cols(); i++)
        ans=A.m(r,i)*B.m(i,c)+ans;
      C.m(r,c,ans);
     };
};

void main()
  {
    Matrix A(4,3);
    Matrix B(3,6);
    Matrix C;

    A.m(0,0,11); A.m(0,1,12); A.m(0,2,13);
    A.m(1,0,21); A.m(1,1,22); A.m(1,2,23);
    A.m(2,0,31); A.m(2,1,32); A.m(2,2,33);
    A.m(3,0,41); A.m(3,1,42); A.m(3,2,43);

    B.m(0,0,11); B.m(0,1,21); B.m(0,2,31); B.m(0,3,41);B.m(0,4,51);B.m(0,5,61);
    B.m(1,0,12); B.m(1,1,22); B.m(1,2,32); B.m(1,3,42);B.m(1,4,52);B.m(1,5,62);
    B.m(2,0,13); B.m(2,1,23); B.m(2,2,33); B.m(2,3,43);B.m(2,4,53);B.m(2,5,63);

    C=A*B;
    A.dump(); cout << endl;
    B.dump(); cout << endl;
    C.dump(); cout << endl;

    multiply(A,B,C);
    A.dump(); cout << endl;
    B.dump(); cout << endl;
    C.dump(); cout << endl;

    cout << "Done.\n";
  }

The "multiply" function produces the correct output, but the overloaded * method does not. That method produces:

4.13e-306 794 1154 1514 1874 2234
794 1454 2114 2774 3434 4094
1154 2114 3074 4034 4994 5954
1514 2774 4034 5294 6554 7814

This answer is mostly correct. Only the (0,0) cell is wrong, it should be 434.

I have no idea what's going wrong here, other than I am getting the wrong answer.

While I could just use the "multiply" function, I suspect that my problem here may be more than just with the overloaded operator.

Most documentation examples don't seem to cover classes of matrices -- so I may have errors on several levels here.

Any advice, or suggestions, will be greatly appreciated.

Thanks,

Tom

Recommended Answers

All 7 Replies

inside the operator*, call the multiply function.

inside the operator*, call the multiply function.

Thanks for this advice, that that option won't really work. First, it's not intuitively obvious how I would go about it. How do you pass a copy of a structure to a function that exists within the structure? An interesting question, for which I wouldn't mind learning the answer. I suppose I could create a copy function within the class, and pass the copy to the multiply function -- but that's adding complications.

However, has has been suggested is a work around, rather than a solution. None of the examples of operator overload I have seen use this type of work around. So, I have to go back and assume that I am doing something wrong with the basic implementation of the function, the class, or both.

Again, any help, or suggestions as to things I might read to find the answer, will be greatly appreciated.

Tom

Whats the problem with :

Matrix Matrix::operator* (const Matrix &B){
Matrix temp;
multiply(*this,B,temp);
return temp;
}

Whats the problem with :

Matrix Matrix::operator* (const Matrix &B){
Matrix temp;
multiply(*this,B,temp);
return temp;
}

Nothing is wrong with *this, except that it doesn't solve the problem. Calling multiply within the operator* function produces the same incorrect answer in the resulting matrix.

Nothing is wrong with *this, except that it doesn't solve the problem. Calling multiply within the operator* function produces the same incorrect answer in the resulting matrix.

Thats a problem with you multiply function then. Check the formula.

Thats a problem with you multiply function then. Check the formula.

Can you be more specific?

The multiply function does produce the correct answer when invoked on its own. I've tested it with a number of different matrices, and it works every time. So, I am fairly sure that the problem does not lie with the formula.

But, even if it was a formula problem, why would the multiply function produce a different answer from the operator* function, when the body of the code for the two functions are essentially the same (this is especially true when you invoke multiply from within operator*).

I am having a problem with overloading an operator within a class structure. Below is the program that illustrates my problem. It defines a class Matrix, creates two matrices and multiplies them.

I created to multiplication functions. The first is a straight function, the second uses the overloaded * operator. The two methods produce different results.

I think it has to do with default construction and copying. Here's your code changed slightly:

#include <iostream>
#include <fstream>
using namespace std;

class Matrix
 {
  private:
    int ROWS, COLUMNS;
    double *M;
  public:
    Matrix() { };                                                         //default constructor
    Matrix(int R, int C){ROWS=R; COLUMNS=C; M=new double[ROWS*COLUMNS];}; //constructor
    ~Matrix() {delete[] M;};        // destructor
    int rows() const {return ROWS;}
    int cols() const {return COLUMNS;}
    void set(int R, int C) {ROWS=R; COLUMNS=C; M=new double[ROWS*COLUMNS];};
    void m (int R, int C, double V) {M[R*COLUMNS+C]=V;};
    double m (int R, int C) const {return M[R*COLUMNS+C];};
    void dump() {for (int r=0; r<ROWS; r++) {for (int c=0; c<COLUMNS; c++)
                    cout << M[r*COLUMNS+c]<< " "; cout << endl;};};
    void dump(fstream &fout) {for (int i=0; i<(ROWS*COLUMNS); i++)
                    {fout << M[i]; if (i!=(ROWS*COLUMNS-1)) fout << ", ";};};
    Matrix operator * (Matrix &);
  };

Matrix Matrix::operator* (Matrix &B)
 {
  Matrix C;
  double ans;
  C.set(rows(), B.cols());
  for (int r=0; r<rows(); r++)
    for (int c=0; c<B.cols(); c++)
      {
       ans=0;
       for (int i=0; i<cols(); i++)
         ans=m(r,i)*B.m(i,c)+ans;
       C.m(r,c,ans);
      };
  return(C);
 };

void multiply(const Matrix &A, const Matrix &B, Matrix &C)  //This Works!! Or at least seems to
{
 double ans;
 C.set(A.rows(), B.cols());
 for (int r=0; r<A.rows(); r++)
   for (int c=0; c<B.cols(); c++)
     {
      ans=0;
      for (int i=0; i<A.cols(); i++)
        ans=A.m(r,i)*B.m(i,c)+ans;
      C.m(r,c,ans);
     };
};

int main()
  {
    Matrix A(4,3);
    Matrix B(3,6);

    A.m(0,0,11); A.m(0,1,12); A.m(0,2,13);
    A.m(1,0,21); A.m(1,1,22); A.m(1,2,23);
    A.m(2,0,31); A.m(2,1,32); A.m(2,2,33);
    A.m(3,0,41); A.m(3,1,42); A.m(3,2,43);

    B.m(0,0,11); B.m(0,1,21); B.m(0,2,31); B.m(0,3,41);B.m(0,4,51);B.m(0,5,61);
    B.m(1,0,12); B.m(1,1,22); B.m(1,2,32); B.m(1,3,42);B.m(1,4,52);B.m(1,5,62);
    B.m(2,0,13); B.m(2,1,23); B.m(2,2,33); B.m(2,3,43);B.m(2,4,53);B.m(2,5,63);

    Matrix C=A*B;
    A.dump(); cout << endl;
    B.dump(); cout << endl;
    C.dump(); cout << endl;

    multiply(A,B,C);
    A.dump(); cout << endl;
    B.dump(); cout << endl;
    C.dump(); cout << endl;

    cout << "Done.\n";
  }

/* my output
11 12 13 
21 22 23 
31 32 33 
41 42 43 

11 21 31 41 51 61 
12 22 32 42 52 62 
13 23 33 43 53 63 

434 794 1154 1514 1874 2234 
794 1454 2114 2774 3434 4094 
1154 2114 3074 4034 4994 5954 
1514 2774 4034 5294 6554 7814 

11 12 13 
21 22 23 
31 32 33 
41 42 43 

11 21 31 41 51 61 
12 22 32 42 52 62 
13 23 33 43 53 63 

434 794 1154 1514 1874 2234 
794 1454 2114 2774 3434 4094 
1154 2114 3074 4034 4994 5954 
1514 2774 4034 5294 6554 7814 

Done.
*/

I've never done a matrix class, so I decided to tinker a bit.

#include <iostream>
#include <fstream>
using namespace std;

class Matrix
{
   int rows, cols;
   double *data;
public:
   Matrix(int r = 0, int c = 0)
   : rows(r)
   , cols(c)
   , data(new double[rows * cols])
   {
   }
   ~Matrix()
   {
      delete[] data;
   }
   int getrows() const
   {
      return rows;
   }
   int getcols() const
   {
      return cols;
   }
   double& operator() (int r, int c)
   {
      return data[r * cols + c];
   }
   double operator() (int r, int c) const
   {
      return data[r * cols + c];
   }
   friend ostream& operator<< (ostream &o, const Matrix &m)
   {
      for ( int r = 0; r < m.rows; ++r )
      {
         for ( int c = 0; c < m.cols; ++c )
         {
            o << m.data[r * m.cols + c] << " ";
         }
         o << endl;
      }
      return o;
   }
};

Matrix operator* (const Matrix &a, const Matrix &b)
{
   int rows = a.getrows();
   int cols = b.getrows();
   Matrix result(rows, cols);
   for ( int r = 0; r < rows; ++r )
   {
      for ( int c = 0; c < cols; ++c )
      {
         double sum = 0;
         for ( int i = 0; i < cols; ++i )
         {
            sum += a(r, i) * b(i, c);
         }
         result(r, c) = sum;
      }
   }
   return result;
}

int main()
{
   Matrix A(4,3);
   Matrix B(3,6);

   A(0,0) = 11; A(0,1) = 12; A(0,2) = 13;
   A(1,0) = 21; A(1,1) = 22; A(1,2) = 23;
   A(2,0) = 31; A(2,1) = 32; A(2,2) = 33;
   A(3,0) = 41; A(3,1) = 42; A(3,2) = 43;

   B(0,0) = 11; B(0,1) = 21; B(0,2) = 31; B(0,3) = 41; B(0,4) = 51; B(0,5) = 61;
   B(1,0) = 12; B(1,1) = 22; B(1,2) = 32; B(1,3) = 42; B(1,4) = 52; B(1,5) = 62;
   B(2,0) = 13; B(2,1) = 23; B(2,2) = 33; B(2,3) = 43; B(2,4) = 53; B(2,5) = 63;

   Matrix C = A * B;
   cout << A << endl;
   cout << B << endl;
   cout << C << endl;
   cout << "Done.\n";
}

/* my output
11 12 13
21 22 23
31 32 33
41 42 43

11 21 31 41 51 61
12 22 32 42 52 62
13 23 33 43 53 63

434 794 1154
794 1454 2114
1154 2114 3074
1514 2774 4034

Done.
*/
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.