# Overloading operator+

Printable View

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 01-12-2010
SterlingM
Overloading operator+
I am trying to make a Matrix class that has overloaded operators for +, =, and *. I am stuck on overloading + and =.
Code:

```//assignment operator Matrix &Matrix::operator=(Matrix &whatever) {         if(getRows() != whatever.getRows() || getCols() != whatever.getCols()) {                 cout<<"The matrices are not the same size!"<<endl;        //if they are the same size                 return 0;         }         else {        //else if they are not the same size                 for(int r=0;r<getRows();r++)                         for(int c=0;c<getCols();c++)                                 this->getTerms()[r][c] = whatever.getTerms()[r][c];        //set the term         }        //end else         return *this; }        //END OPERATOR=```
The problem here is that the compiler won't let me return 0. If the matrices are not the same size, I want the function (or whole program) to end there. How can I end the function?

Code:

```Matrix Matrix::operator+(Matrix &additive) {                if( (getRows() != additive.getRows()) || (getCols() != additive.getCols()) )        //if they are not the same size                 cout<<"The matrices cannot be added because they are not the same size!"<<endl;         else {                 Matrix sum(getRows(), getCols(), 'S');                 for(int r=0;r<getRows();r++)                         for(int c=0;c<getCols();c++)                                 sum.getTerms()[r][c] = getTerms()[r][c] + additive.getTerms()[r][c];                 return sum;         }        //end else }        //END OPERATOR+```
Here there is the same problem in the if statement as operator=. But also, I thought I should not return a reference a because 1) a new matrix needs to be made and 2) I would be returning a reference to a local variable. But whenever I try to use the operator, the program stops working. How can I make this work? Any help is appreciated.
• 01-13-2010
laserlight
Quote:

Originally Posted by SterlingM
The problem here is that the compiler won't let me return 0. If the matrices are not the same size, I want the function (or whole program) to end there. How can I end the function?

Throw an exception. Alternatively, you could turn this into a class template and have the size specified at compile time, in which case it would be a type error to assign to a matrix of different size.

Quote:

Originally Posted by SterlingM
Here there is the same problem in the if statement as operator=. But also, I thought I should not return a reference a because 1) a new matrix needs to be made and 2) I would be returning a reference to a local variable. But whenever I try to use the operator, the program stops working. How can I make this work?

Yes, you have the right idea. Maybe the copy constructor has an incorrect implementation.

By the way, unless you have special reasons for doing otherwise, the parameters of operator= and operator+ should be const references, and operator+ should be a const member function (or a non-member function).
• 01-13-2010
SterlingM
Ah! I forgot all about exceptions! And I'm pretty sure you're right about the copy constructor. I'll post it whenever I get it working if anyone else happens to read this and wants to know. Thanks.
• 01-13-2010
SterlingM
I have only made exception classes in Java so I'm unfamiliar with the details of it in C++. Whenever you call
Code:

`runtime_error(const string&);`
Does that make a window pop-up telling you
"Debug Error!
Program: ...filename...
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information."
Then the abort, retry, ignore options?

If so, I guess it's working correctly but not exactly how I'd like it to. If that sounds wrong, I can include some code. This only happens when I throw the exception. If the matrices are the same size, the program works fine.
• 01-13-2010
SterlingM
Okay well I'm pretty sure that window came up because instead of having a try..catch I just threw the exception. So I added a try..catch and the only problem is I'm not sure what to return in the function.

Code:

```Matrix Matrix::operator+(const Matrix &additive) {         try {                 if( (getRows() != additive.getRows()) || (getCols() != additive.getCols()) ) //if they are not the same size                         throw DifferentSizeException();        //throw exception                 else {                         Matrix sum(getRows(), getCols(), 'S');                         for(int r=0;r<getRows();r++)                                 for(int c=0;c<getCols();c++)                                         sum.getTerms()[r][c] = getTerms()[r][c] + additive.getTerms()[r][c];                         return sum;                 }        //end else         }        //end try         catch(DifferentSizeException &e) {                 cout<<"The matrices cannot be added because they are not the same size."<<endl;         }        //end catch }        //END OPERATOR+```
See if the exception gets thrown, the function resumes and contains nothing else. At that point though, I DON'T want to return a matrix because the matrices should not be added.
• 01-13-2010
laserlight
Quote:

Originally Posted by SterlingM
I have only made exception classes in Java so I'm unfamiliar with the details of it in C++.

You can have your exception class inherit from std::exception (#include <exception>), but it is usually easier to derive from std::logic_error or std::runtime_error (#include <stdexcept>) since you only need to write a constructor that invokes the base class constructor when you do so.

Quote:

Okay well I'm pretty sure that window came up because instead of having a try..catch I just threw the exception.
Yes, so a try/catch block is appropriate, but you should catch the exception by (const) reference.

However, you are catching the exception in the same function that threw it. That is usually pointless. What you want to do is to just throw the exception so that the caller can handle it, e.g.,
Code:

```Matrix Matrix::operator+(const Matrix &additive) const {     if ( (getRows() != additive.getRows()) || (getCols() != additive.getCols()) ) {         throw DifferentSizeException();     }     // Addition can be performed as the matrices have the same size.     Matrix sum(getRows(), getCols(), 'S');     for (int r = 0; r < getRows(); ++r) {         for (int c = 0; c < getCols(); ++c) {             sum.getTerms()[r][c] = getTerms()[r][c] + additive.getTerms()[r][c];         }     }     return sum; }```
Incidentally, consider implementing operator+= as a member, and then you can implement operator+ as a non-member non-friend pretty easily:
Code:

```Matrix& Matrix::operator+=(const Matrix& other) {     if ( (getRows() != other.getRows()) || (getCols() != other.getCols()) ) {         throw DifferentSizeException();     }     // Addition can be performed as the matrices have the same size.     for (int r = 0; r < getRows(); ++r) {         for (int c = 0; c < getCols(); ++c) {             getTerms()[r][c] += other.getTerms()[r][c];         }     }     return *this; } Matrix operator+(Matrix x, const Matrix& y) {     return x += y; }```
If getRows(), getCols() and getTerms() are all public, you could actually implement both as non-member non-friend functions.
• 01-13-2010
SterlingM
Awesome. Thanks for the information and advice. But one question - why would I want to make the operators non-member non-friend functions? What are the advantages (if it's not a super long list heh) over having them as member functions?
• 01-13-2010
laserlight
Quote:

Originally Posted by SterlingM
Awesome. Thanks for the information and advice. But one question - why would I want to make the operators non-member non-friend functions? What are the advantages (if it's not a super long list heh) over having them as member functions?

You could get a summary by reading an interview of Bjarne Stroustrup concerning The C++ Style Sweet Spot (in particular, the "Designing Simple Interfaces" section). Scott Meyers explains How Non-Member Functions Improve Encapsulation, and Herb Sutter dissects a negative example from the C++ standard library in GotW #84: Monoliths "Unstrung".
• 01-13-2010
SterlingM
Thank you for the help and especially the quick responses!
• 01-13-2010
SterlingM
This is off topic of the thread now I think but I have a quick question about making those functions non-member non-friend. I tried making them both non member non friend and the compiler gives me an error for each saying they have too many parameters. But if I make them friend functions they work fine.

Code:

```class Matrix {         Matrix operator+=(Matrix &, const Matrix &);        //overload +=         Matrix operator+(Matrix &, const Matrix &);        //overload +         friend ostream &operator<<(ostream &, const Matrix &);        //printing matricies public:```
Code:

```Matrix operator+=(Matrix &additive1, const Matrix &additive2) {         if( (additive1.getRows() != additive2.getRows()) || (additive1.getCols() != additive2.getCols()) )                 throw DifferentSizeException();         else {                 for(int r=0;r<additive1.getRows();r++)                         for(int c=0;c<additive1.getCols();c++)                                 additive1.getTerms()[r][c] += additive2.getTerms()[r][c];         }        //end else         return additive1; }        //END OPERATOR+= Matrix operator+(Matrix &additive1, const Matrix &additive2) {         return additive1 += additive2; }```
If I compile it like that I get the errors. But like I said, if I make the functions friends they work fine. Why is that?
• 01-13-2010
laserlight
It looks like you are trying to declare them as member functions even though you did not intend to do so.
• 01-13-2010
SterlingM
So...they would go in the file that my main function is in? Wouldn't that be bad for anyone wanting to reuse the Matrix class because they would have to implement the functions on their own instead of them being readily available?
• 01-13-2010
laserlight
No, they would be declared in the same header and namespace as your Matrix class, and you could implement them in the same source file that stores the implementation of the Matrix member functions.

You might have a few convenience functions for Matrix that you wish to make optional, in which case you should declare them in the same namespace but in a different header file, and also implement them in a different source file.
• 01-13-2010
SterlingM
Well whenever I do that I get a ton (71 to be exact) of compiler errors. This is what I'm compiling for Matrix.h and Matrix.cpp.

Code:

```#ifndef MATRIX_H #define MATRIX_H #pragma once #include <iostream> using std::ostream; using std::istream; Matrix &operator+=(Matrix &, const Matrix &);        //overload += Matrix &operator+(Matrix &, const Matrix &);        //overload + class Matrix {         friend ostream &operator<<(ostream &, const Matrix &);        //printing matricies public:         Matrix(const Matrix &);         Matrix(int, int, char);         ~Matrix(void);         void setTerms();        //puts terms into the matrix         //getter functions         char getName() const;         int getRows() const;         int getCols() const;         double **getTerms() const;         //overloaded operators         Matrix &operator=(const Matrix &);        //assignment operator         Matrix &operator*(double &);        //multiply matrix by a non-matrix         Matrix &operator*(Matrix &);        //multiple matrix by another matrix         //Matrix operator+(const Matrix &);                //add one matrix to another. DNR REFERENCE private:         double **terms;         int const rows;         int const cols;         char const name; }; #endif```
Code:

```//MATRIX.CPP #include "Matrix.h" #include "DifferentSizeException.h" #include <iostream> using std::cout; using std::cin; using std::endl; #include <string> using std::string; Matrix &operator+=(Matrix &additive1, const Matrix &additive2) {         if( (additive1.getRows() != additive2.getRows()) || (additive1.getCols() != additive2.getCols()) )                 throw DifferentSizeException();         else {                 for(int r=0;r<additive1.getRows();r++)                         for(int c=0;c<additive1.getCols();c++)                                 additive1.getTerms()[r][c] += additive2.getTerms()[r][c];         }        //end else         return additive1; }        //END OPERATOR+= Matrix &operator+(Matrix &additive1, const Matrix &additive2) {         return additive1 += additive2; }        //END OPERATOR+ Matrix::Matrix(const Matrix &aMatrix) : rows(aMatrix.getRows()), cols(aMatrix.getCols()), name(aMatrix.getName()) {         terms = new double *[rows];         for(int i=0;i<rows;i++)                 *(terms+i) = new double[cols];                for(int r=0;r<getRows();r++)                 for(int c=0;c<getCols();c++)                         getTerms()[r][c] = aMatrix.getTerms()[r][c]; }        //END COPY CONSTRUCTOR //constructor Matrix::Matrix(int r, int c, char n) : rows(r), cols(c), name(n) {         terms = new double *[getRows()];         for(int i=0;i<getRows();i++)                 *(terms+i) = new double[cols]; }        //END CONSTRUCTOR W/ NAME //destructor Matrix::~Matrix(void) { delete [] terms; }        //delete 2d array //GETTER FUNCTIONS char Matrix::getName() const {return name;} int Matrix::getRows() const {return rows;} int Matrix::getCols() const {return cols;} double **Matrix::getTerms() const {return terms;} //END GETTER FUNCTIONS //user inputs terms to be put into the matrix void Matrix::setTerms() {         cout<<"**********Matrix "<<getName()<<"**********"<<endl;         for(int r=0;r<rows;r++) {                 for(int c=0;c<cols;c++) {                         double theTerm;                         cout<<"Enter the term for element ["<<r<<", "<<c<<"]."<<endl;                         cin>>theTerm;                         getTerms()[r][c] = theTerm;                 }        //end inner for         }        //end double for }        //END SETTERMS() //print matrix ostream &operator<<(ostream &output, const Matrix &theMatrix) {         cout<<"--Matrix "<<theMatrix.getName()<<"--"<<endl;         for(int r = 0;r<theMatrix.getRows();r++) {                 for(int c = 0;c<theMatrix.getCols();c++) {                         output<<theMatrix.getTerms()[r][c]<<"\t";                         if( (c+1) == theMatrix.getCols() )                                 output<<endl;                 }        //end inner for         }        //end double for         return output; }        //END OPERATOR<< //assignment operator Matrix &Matrix::operator=(const Matrix &whatever) {         if(getRows() != whatever.getRows() || getCols() != whatever.getCols())                 throw DifferentSizeException();         else {        //else if they are not the same size                 for(int r=0;r<getRows();r++)                         for(int c=0;c<getCols();c++)                                 getTerms()[r][c] = whatever.getTerms()[r][c];        //set the individual term         }        //end else         return *this; }        //END OPERATOR= //multiply matrix by a number Matrix &Matrix::operator*(double &constant) {         for(int r=0;r<getRows();r++)                 for(int c=0;c<getCols();c++)                         getTerms()[r][c] *= constant;         return *this; }        //END OPERATOR*(DOUBLE) //Matrix Matrix::operator+(const Matrix &additive) { //                if( (getRows() != additive.getRows()) || (getCols() != additive.getCols()) ) //if they are not the same size //                        throw DifferentSizeException();        //throw exception //                else { //                        Matrix sum(getRows(), getCols(), 'S'); //                        for(int r=0;r<getRows();r++) //                                for(int c=0;c<getCols();c++) //                                        sum.getTerms()[r][c] = getTerms()[r][c] + additive.getTerms()[r][c]; //                        return sum;        //return the sum //                }        //end else //}        //END OPERATOR+ //TODO********************************* //multiply matrix by another matrix Matrix &Matrix::operator*(Matrix &secondFactor) {         return *this; }        //END OPERATOR*(MATRIX)```
I know most of that is unnecessary, but I'm including it just to show exactly what I'm compiling. I feel like I get the gist of what you're saying, but I'm slightly off. Declaring and implementing the operator functions where they are at is what I'm getting from what you said. What is wrong with it?
• 01-13-2010
laserlight
Do not use using declarations or using directives at global or namespace scope in header files, or before including a file.

Now, one possible problem lies with this member function:
Code:

`double **getTerms() const;`
The problem is that you want to call it from a non-const reference to Matrix. You should actually use const overloading:
Code:

```double** getTerms(); const double* const * getTerms() const;```
By the way, your destructor does not correctly destroy the member array. It fails to destroy each dynamic array of double. Notice that my operator+ implementation takes the first argument by value, not by reference.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last