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

Operator overloading in C++ of a matrix template

我正在尝试实施 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;
}

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

所以你可以这样做:

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;它会起作用;)。 有关详细信息,请参阅下面我的评论;)

在你的 operator+ 里面,你实际上有 b = (*this) + z。但是,您只需检查 this 中的 rowcol。如果 z 在任一维度上都较小,则您将越界。

您可以检查这种情况并找出 return 如果发生这种情况(或抛出异常,选择权在您):

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

或者您也可以在维度上对 mat class 进行模板化,这将使两个不同大小的矩阵成为不同的类型

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

您的函数内部运行良好。但是正如上面其他人提到的,您的函数签名有问题,导致它们以一种相当奇怪的方式被调用。

我已经在您的代码中添加了一些调试输出来说明正在发生的事情。您应该添加这些更改、编译和 运行.

#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,也不会在 pq 上调用 operator+ 函数。

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