矩阵模板的 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
中的 row
和 col
。如果 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,也不会在 p 或 q 上调用 operator+ 函数。
此代码在退出时也会出现段错误。我认为问题在于创建匿名对象,它使用编译器创建的默认构造函数,它没有设置 row、col 或 intialise 一个.
我正在尝试实施 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
中的 row
和 col
。如果 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,也不会在 p 或 q 上调用 operator+ 函数。
此代码在退出时也会出现段错误。我认为问题在于创建匿名对象,它使用编译器创建的默认构造函数,它没有设置 row、col 或 intialise 一个.