• 12-08-2009
TMG
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 two multiplication methods. The first is a straight function, the second uses
the overloaded * operator. The two methods produce different results.

Code:

```#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:

Code:

```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
• 12-08-2009
anon
Firstly, this code is full of syntax errors, so it is hard to see how it compiles in the first place.

Starting from there not being a header like <fstream.h> in C++ (though probably your somewhat out-of-date compiler has it) and main having to return int.

Besides that you are using const references in the operator overload, and then calling non-const methods on those arguments.

------------

If the code is the same, one should be implemented in terms of the other (Ok, perhaps you are planning to remove the multiply method if you figure this one out?)

-------------

As to the problem, you are violating the rule of three. If you are managing a resource (dynamically allocated array), you'll need to define the destructor, the copy constructor and the overloaded assignment operator. (Or better yet, use a std::vector<double> instead, in which case you won't need any of those.)

As it is, when operator* returns by value, the copy gets a pointer to the array used in the function by C, but that object itself goes out of scope at the end of the function and releases the memory. Using deallocated objects is undefined behavior (e.g, when running the debug version, all the results I got were wrong).