简体   繁体   中英

Operator overloading in C++ of a matrix template

I'm trying to implement a Matrix template. I've overloaded the << , >> and + operators. << and >> are working properly but + is not working as expected. After using the + operator I am getting some random output in the last line. Can anyone tell me what is wrong?

#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
    int row,col;
    V **a;
    mat(int r,int c)
    {
        row=r;
        col=c;
        a=new V*[r];
        for(int i=0;i<row;i++)
        {
            a[i]=new V[col];
        }
    }
    mat(const mat &x)   //Copy constructor
    {
        row=x.row;
        col=x.col;
        a=new V*[row];
        for(int i=0;i<row;i++)
        {
            a[i]=new V[col];
        }
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                a[i][j]=x.a[i][j];
            }
        }
    }
    ~mat()
    {
        //cout << "Deleting Matrix\n" << endl;
        for(int i=0;i<row;i++)
        {
            delete []a[i];
        }
    }
    friend ostream &operator<<(ostream &p,const mat &z)
    {
        for(int i=0;i<z.row;i++)
        {
            for(int j=0;j<z.col;j++)
            {
                p << z.a[i][j] <<" ";
            }
            cout << endl;
        }
        return p;
    }
    friend istream &operator>>(istream &p,mat &z)
    {
        for(int i=0;i<z.row;i++)
        {
            for(int j=0;j<z.col;j++)
            {
                p >> z.a[i][j];
            }
        }
        return p;   
    }
    mat<V> operator+(mat<V> z)
    {
        mat<V> b(row,col);
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                b.a[i][j]=a[i][j]+z.a[i][j];
            }
        }
        return b;
    }
};
int main()
{
    mat<int> p(2,2),q(2,2),z(2,2);
    cin>>p>>q;
    cout<<p<<q<<endl; //working properly
    z=p+q;
    cout<<z<<endl; // getting wrong output here
    return 0;
}

In C++, I recommand to use operator +=, -=, *=, /= and others like them be internal to the class. The operators +, *, -, / should be external.

So you could do something like this:

class A {
    A &operator +=(A const &b) {
        ... code
        return *this;
    }
};

A operator+(A a1, A const &a2) {
    return a1 += a2;
}

thanks to vsoftco for the tip

To answer more precisely to your question, you just did not define the operator= If you do mat z = p + q; it will works ;). See my comments below for further details ;)

Inside of your operator+ you effectively have b = (*this) + z . You only however, check row and col from this . If z is smaller in either dimension you are going to be out of bounds.

You can check for this condition and figure out what to return if that happens (or throw an exception, the choice is yours):

mat<V> operator+(const mat<V>& z) const {
    mat<V> b(row,col);
    if (z.row != row || z.col != col) { return b; }
    //  ...
}

Or you can have the mat class be templated on the dimensions as well, which would make two different size matrices be different types

template <typename T, int Row, int Col>
class mat {
  private:
    T a[Row][Col];
    // ...
};

The internals of your functions are working fine. But as others have mentioned above, there is something wrong with your function signatures, that is causing them to be called in a rather strange way.

I have added some debug output to your code to illustrate what is happening. You should add these changes, compile and run.

#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
    int row,col;
    V **a;
    mat(int r,int c)
    {
        row=r;
        col=c;
        a=new V*[r];
        for(int i=0;i<row;i++)
        {
            a[i]=new V[col];
            for (int cc=0; cc<col;++cc)
            {
                a[i][cc] = -77;
            }
        }
    }
    mat(const mat &x)   //Copy constructor
    {   
        cout << "copy to this: " << this << endl;
        cout << "x: " << &x << endl;
        row=x.row;
        col=x.col;
        a=new V*[row];
        for(int i=0;i<row;i++)
        {
            a[i]=new V[col];
        }
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                a[i][j]=x.a[i][j];
            }
        }
    }
    ~mat()
    {
        //cout << "Deleting Matrix\n" << endl;
        for(int i=0;i<row;i++)
        {
            delete []a[i];
        }
    }
    friend ostream &operator<<(ostream &p,const mat &z)
    {
        for(int i=0;i<z.row;i++)
        {
            for(int j=0;j<z.col;j++)
            {
                p << z.a[i][j] <<" ";
            }
            cout << endl;
        }
        return p;
    }
    friend istream &operator>>(istream &p,mat &z)
    {
        for(int i=0;i<z.row;i++)
        {
            for(int j=0;j<z.col;j++)
            {
                p >> z.a[i][j];
            }
        }
        return p;   
    }
    mat<V> operator+(mat<V> z)
    {
        cout << "plus to this: " << this << endl;
        mat<V> b(row,col);
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                b.a[i][j]=a[i][j]+z.a[i][j];
            }
        }
        return b;
    }
};

int main()
{
    mat<int> p(2,2),q(2,2),z(2,2);
    cin>>p>>q;

    cout<<p<<q<<endl; //working properly

    cout << "Before" << endl;
    cout << "p : " << &p << endl;
    cout << "q : " << &q << endl;
    cout << "z : " << &z << endl;

    cout << "After" << endl;
    z=p+q;
    cout<<q<<endl;
    cout<<z<<endl; // getting wrong output here
    return 0;
}

When I run I see the following output.

Before
p : 0026F75C
q : 0026F748
z : 0026F734
After
copy to this: 0026F61C
x: 0026F748
plus to this: 0026F75C
copy to this: 0026F654
x: 0026F5E8

From this you can see that when the line

z=p+q;

is run, the copy constructor is called to copy q to an anonymous object, then the operator+ function is called on another anonymous object.

Finally, when exiting the operator+ function, the copy constructor is called again, copying the result of operator+ function to a third anonymous object. At no time is anything copied to z , nor is the operator+ function called on p or q .

This code also segfaults on exit. I think the problem lies with creating anonymous objects, which is using the default constructor created by the compiler, which does not set row , col or intialise a .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM