-1

i write a class and i have a problem with adding matrices. I know that i have to overload operator +, but i don't know how exactly. any ideas ?

 class CMatrix
  {
    private:
            int Rows;
            int Columns;
            float* pData;

    public:
            CMatrix(void);
            CMatrix(int rows, int columns);               

            void setElement(int row, int column, float element);
            float getElement(int row, int column);
   ...};
    istream& operator>>(istream& in, CMatrix& matrix)
     {
in >> matrix.Rows;
in >> matrix.Columns;

for(int i = 0; i < matrix.Rows; i++)
    for(int j = 0; j < matrix.Columns; j++)
        in >> *(matrix.pData + i * matrix.Columns + j);

return in;
    }


      CMatrix::CMatrix(int rows, int columns)
    {
    Rows = rows;
    Columns = columns;
    pData = new float[Rows * Columns];

    float* pEnd = &pData[Rows * Columns];

    for(float* p = pData; p < pEnd; p++)
            *p = 0.0;
      } 

    void CMatrix::setElement(int row, int column, float element)
    {

     *(pData+  row * Columns + column) = element;

     }

    float CMatrix::getElement(int row, int column)
     {
       return *(pData + row * Columns + column);
      }

I overloaded operators '<<' ,'>>' , but i have a problem with operator +.

Unfortunatelly i have less than 10 reputation...so If i write:

 CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs)
    {
 Cmatrix result (Rows,Columns);
for(int i=0; i <Rows ; i++)
for( int j=0; j<Columns; j++)
 result.setElement(i,j)  = lhs.getElement(i,j) + rhs.getElement(i,j);   
return result;      
 }


 int main()
   {
const int n = 10, m = 5;
 CMatrix m1(n, m);
     CMatrix m2(n, m);

for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++)
        m1.setElement(i, j, (float)(i * m + j));

    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        m2.setElement(i, j, (float)(i * m + j));
    cout<<m1+m2;  // it doesn't work
   Thanks all for help, i did it at last...
volly
  • 147
  • 1
  • 1
  • 8

3 Answers3

6

Unless you need access to the private members of CMatrix to perform the computation, I would recommend that you create a non-member function with the following prototype:

CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs)
{
  // Do the work

  // You may need to throw exceptions based on incompatibilities between
  // matrix configurations (i.e., dimensions)
}

You also really should add a copy constructor, destructor, and assignment operators (maybe a move constructor and move assignment as well) or consider disabling these operations. If you do not, you will run into serious issues with the compiler supplied defaults if code employs them.

You most definitely need to add a destructor, because you will leak memory if you do not.

Michael Goldshteyn
  • 71,784
  • 24
  • 131
  • 181
  • my destructor- CMatrix::~CMatrix(void) { delete [] pData; } – volly Aug 07 '13 at 16:39
  • You can't return false from a function that returns a CMatrix. Think about it, it doesn't make sense. If the function is to work properly, it must thrown an exception. – Michael Goldshteyn Aug 07 '13 at 16:43
  • OK, my foult.. but i still don't know how i can write this operator+... i'd like call out this operator like that- cout<< m1+m2; – volly Aug 07 '13 at 16:46
4

The best way to overload operators in C++ is to overload the arithmetic operators (operator+ , operator-, etc) based in asigment operators (operator+= and its colleages).

In your case:

Matrix& operator+=(const Matrix& other)
{
    /* Add operation stuff... */

    return *this;
}

Matrix operator+(const Matrix& llhs , const Matrix& rhs)
{
    Matrix result( lhs ); //Copy of the first operand.
    result += rhs; //Add computation.
    return result; //NRVO-friendly implementation
}

This implementation has two advantages:

  • Is scalable: The implementation of + is based on +=. So the behaviour of the operators is coherent, and mantenible (No duplied code).
  • Is efficient: The assigment operators are more cache-friendly than binary operators (You are operating with the same instance, instance of using two and generating the result), and this implementation uses only one copy (The explicit copy used in the inicialization of result), because this code is designed to let the compiler to do the NRVO.

Advanced topic: Automaticating operators overloading

You can take advantage of the Curiously Recurrent Template Pattern to automatize the implementation of operator overloadings.

What is the CRTP?

The CRTP is a C++ idiom in wich a class inherits from a template class with it as template argumment. For example:

template<typename T>
struct Base { /* ... */ };

struct Derived : public Base<Derived> { /* ... */ };

The key of the CRTP is that the base class has access (knows) to the class that derives from it.

Operators automatication:

In our case, we could use this access to the derived case to implement a certain operator in the base class, based on an operator that has to be implemented by the derived class.

Let me explain this with an example: The implementation of inequality operator based on the implentation of the equality operator provided by the user.

template<typename T>
struct EqualityHelper
{
    friend bool operator !=(const T& lhs , const T& rhs)
    {
        return !(lhs == rhs); //We use the operator== that T (The user class) implements.
    }
};

We could use that CRTP base as a helper class to implement the operator!= of any class that inherits from it. For example:

class Foo : public EqualityHelper<Foo> //Magic!
{
    friend bool operator==(const Foo& lhs , const Foo& rhs)
    {
        /* Equality implementation */
    }
};

int main()
{
   Foo a,b;

   if( a != b) //Muahahahaha
   {
      /* ... */
   }
}

This could be extended for any operator. The best example to see the power of this method, is the comparison operators. The entire set of comparison operators could be implemented basid in one of them ( a > b is b < a , a <= b is !(a > b), etc):

template<typename T>
struct ComparisonHelper //Comparison operators based in operator> provided by the user
{
    friend bool operator<(const T& lhs , const T& rhs) { return rhs < lhs; }
    friend bool operator<=(const T& lhs , const T& rhs) { return !(lhs > rhs); }
    friend bool operator>=(const T& lhs , const T& rhs) { return !(lhs < rhs); } 
};

Finally, we can take advantage of multiple inheritance to use more than one helper at the same time:

//The complete set of logical comparison operators in six mantenible lines of code!
class Foo : public EqualityHelper<Foo> , public ComparisonHelper<Foo> 
{
   friend bool operator==(const Foo& lhs , const Foo& rhs)
   {
     /* Equality implementation */
   }

   friedn bool operator>(const Foo& lhs , const Foo& rhs)
   {
     /* Comparison implementation */
   }
}

The Boost libraries have a header with a set of helpers implemented with this method: http://www.boost.org/doc/libs/1_54_0/libs/utility/operators.htm

Manu343726
  • 13,969
  • 4
  • 40
  • 75
0

I would simply comment on Michael Goldshteyn's post, but I guess I don't have enough reputation to do that (lol) so consider this an comment on his post:

If you need the + operator to access private data of your CMatrix class (as it will need to do in this case), you can declare this function a friend inside of you CMatrix class by inserting the line:

friend CMatrix operator+(const CMatrix &, const CMatrix &);

anywhere inside of your CMatrix class definition. This allows the overloaded operator function that you define elsewhere to access private and protected members of your class (like your pData member).

user2548343
  • 731
  • 5
  • 12
  • ok, but i still dont know how it works.. i can overload operator generally, but in this example i dont. – volly Aug 07 '13 at 16:58