运算符在C ++中重载矩阵模板

时间:2016-04-12 22:17:59

标签: c++ operator-overloading

我正在尝试实施Matrix模板。我重载了<<>>+运算符。 <<>>工作正常但+未按预期工作。使用+运算符后,我在最后一行得到一些随机输出。谁能告诉我有什么问题?

#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;
}

3 个答案:

答案 0 :(得分:2)

在C ++中,我建议使用operator + =, - =,* =,/ =和类似的其他内容一样。运算符+,*, - ,/应该是外部的。

所以你可以这样做:

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

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

感谢vsoftco的提示

为了更准确地回答您的问题,您只是没有定义operator = 如果你做mat z = p + q;它会工作;)。 有关详细信息,请参阅下面的评论;)

答案 1 :(得分:0)

operator+内,您实际拥有b = (*this) + z。但是,您只能从row检查colthis。如果z在任一维度上都较小,那么您将会超出范围。

你可以检查这个条件并找出如果发生这种情况会返回什么(或抛出异常,选择是你的):

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

或者你也可以在尺寸上模仿mat类,这会使两个不同大小的矩阵成为不同的类型

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

答案 2 :(得分:0)

你的功能内部工作正常。但正如其他人在上面提到的那样,你的函数签名有问题,导致它们以一种相当奇怪的方式被调用。

我在代码中添加了一些调试输出来说明发生了什么。您应该添加这些更改,编译并运行。

#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;
}

当我跑步时,我看到以下输出。

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

从这里你可以看到当行

Z = P + Q;

运行

,调用复制构造函数将 q 复制到匿名对象,然后在另一个匿名对象上调用operator +函数。

最后,当退出operator +函数时,再次调用复制构造函数,将operator +函数的结果复制到第三个匿名对象。任何时候都不会复制到 z ,也不会在 p q 上调用operator +函数。

此代码在退出时也会出现段错误。我认为问题在于创建匿名对象,它使用编译器创建的默认构造函数,它不设置 col 或intialise a