如何使用静态成员函数创建一个矩阵,然后可以使用运算符重载打印该矩阵?
How to use a static member function to create a matrix which can then be printed using operator overloading?
使用构造函数和运算符重载的工作原理如下,我的目标是创建一个 2x4 的零矩阵:
Matrix::Matrix(const int noOfRowss, const int noOfCols){
this->noOfRows=noOfRowss;
this->noOfColums=noOfCols;
data= new double[noOfRows*noOfColumns];
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfColumns; j++){
int index = i*noOfColumns + j;
data[index]=0;
}
}
}
std::ostream& operator<<(std::ostream& output, const Matrix& rhs){
for(int i=0; i< rhs.noOfRows; i++){
for(int j=0; j<rhs.noOfColumns; j++){
int index = i*rhs.noOfColumns + j;
output<<rhs.data[index]<< "\t";
}
output<<std::endl;
}
return output;
}
然而,当我尝试使用静态成员函数时,我遇到了以下代码的分段错误(请参阅下面的测试文件中的实现):
Matrix Matrix::Zeros(const int noOfRows, const int noOfCols){
Matrix out;
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
out.data[index]=0;
}
}
}
我不确定我是否正确地实现了静态成员函数,我的问题是在我的头函数中我需要使用以下变量:
int noOfRows;
int noOfColumns;
double *data;
int GetIndex(const int rowIdx, const int columnIdx) const;
并且在我的测试文件中,我想实现这个静态成员函数如下:
Matrix matrix = Matrix::Zeros(2,4);
cout<<matrix<<endl;
我需要保留 data 变量的原因是它可以在 operator<< 重载函数中使用,因为它以前用于构造函数。然而,在我的静态成员函数中尝试了几种不同的变体后,我并没有像以前那样轻松地将我的矩阵存储在数据变量中。有人有什么建议吗?
所以,我看到您的静态函数显然首先执行此操作。
Matrix output;
但是,您显示的构造函数代码有两个参数,即行数和列数。
据此,我必须得出结论,您还必须有一个默认构造函数,它可能构造一个空矩阵,其中包含一个空 data
向量。
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
output.data[index]=0;
}
}
然后,尝试在此处初始化 default-constructed 矩阵的内容,但没有有效初始化的 data
成员。
这不会有好结果...
P.S.,你可能也想读这个:RAII。我怀疑您的 class 在这方面也会有相关问题。与使用 double *data
成员不同,使用 std::vector<double>
会更好,并且很可能避免这方面的一系列陷阱。
您需要指定 out
对象的大小,就像那样(否则,您将 out.data
超出范围):
Matrix Matrix::Zeros(const int noOfRows, const int noOfCols){
Matrix out(noOfRows*noOfCols); // changed here
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
out.data[index]=0;
}
}
}
如果这样做,至少遵循 rule of three 会更安全,因为使用 Matrix::Zeros
很可能会在您的代码中通过复制构造或通过复制赋值(导致如果定义不正确,则会出现更多段错误,使用默认实现的编译器会导致 double*
指针被弄乱)。正如 Sam Varshavchik 所指出的,使用 std::vector<double>
而不是 double*
将使这些默认实现在您的情况下运行良好。
但是,对于您要解决的具体问题,我建议您只需修改构造函数,使其能够确定默认矩阵内容,这可能会更容易:
Matrix::Matrix(const int noOfRowss, const int noOfCols, double defaultValue)
{
this->noOfRows=noOfRowss;
this->noOfColums=noOfCols;
data= new double[noOfRows*noOfColumns];
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfColumns; j++){
int index = i*noOfColumns + j;
data[index]=defaultValue;
}
}
}
在头文件中,可以有:
class Matrix
{
public:
Matrix(const int noOfRowss, const int noOfCols, double defaultValue = 0);
...
};
然后:
std::cout << Matrix(4,2) << std::endl; // displays a 4x2 matrix filled with zeros
std::cout << Matrix(4,2,1) << std::endl; // displays a 4x2 matrix filled with ones
使用构造函数和运算符重载的工作原理如下,我的目标是创建一个 2x4 的零矩阵:
Matrix::Matrix(const int noOfRowss, const int noOfCols){
this->noOfRows=noOfRowss;
this->noOfColums=noOfCols;
data= new double[noOfRows*noOfColumns];
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfColumns; j++){
int index = i*noOfColumns + j;
data[index]=0;
}
}
}
std::ostream& operator<<(std::ostream& output, const Matrix& rhs){
for(int i=0; i< rhs.noOfRows; i++){
for(int j=0; j<rhs.noOfColumns; j++){
int index = i*rhs.noOfColumns + j;
output<<rhs.data[index]<< "\t";
}
output<<std::endl;
}
return output;
}
然而,当我尝试使用静态成员函数时,我遇到了以下代码的分段错误(请参阅下面的测试文件中的实现):
Matrix Matrix::Zeros(const int noOfRows, const int noOfCols){
Matrix out;
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
out.data[index]=0;
}
}
}
我不确定我是否正确地实现了静态成员函数,我的问题是在我的头函数中我需要使用以下变量:
int noOfRows;
int noOfColumns;
double *data;
int GetIndex(const int rowIdx, const int columnIdx) const;
并且在我的测试文件中,我想实现这个静态成员函数如下:
Matrix matrix = Matrix::Zeros(2,4);
cout<<matrix<<endl;
我需要保留 data 变量的原因是它可以在 operator<< 重载函数中使用,因为它以前用于构造函数。然而,在我的静态成员函数中尝试了几种不同的变体后,我并没有像以前那样轻松地将我的矩阵存储在数据变量中。有人有什么建议吗?
所以,我看到您的静态函数显然首先执行此操作。
Matrix output;
但是,您显示的构造函数代码有两个参数,即行数和列数。
据此,我必须得出结论,您还必须有一个默认构造函数,它可能构造一个空矩阵,其中包含一个空 data
向量。
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
output.data[index]=0;
}
}
然后,尝试在此处初始化 default-constructed 矩阵的内容,但没有有效初始化的 data
成员。
这不会有好结果...
P.S.,你可能也想读这个:RAII。我怀疑您的 class 在这方面也会有相关问题。与使用 double *data
成员不同,使用 std::vector<double>
会更好,并且很可能避免这方面的一系列陷阱。
您需要指定 out
对象的大小,就像那样(否则,您将 out.data
超出范围):
Matrix Matrix::Zeros(const int noOfRows, const int noOfCols){
Matrix out(noOfRows*noOfCols); // changed here
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfCols; j++){
int index = i*noOfCols + j;
out.data[index]=0;
}
}
}
如果这样做,至少遵循 rule of three 会更安全,因为使用 Matrix::Zeros
很可能会在您的代码中通过复制构造或通过复制赋值(导致如果定义不正确,则会出现更多段错误,使用默认实现的编译器会导致 double*
指针被弄乱)。正如 Sam Varshavchik 所指出的,使用 std::vector<double>
而不是 double*
将使这些默认实现在您的情况下运行良好。
但是,对于您要解决的具体问题,我建议您只需修改构造函数,使其能够确定默认矩阵内容,这可能会更容易:
Matrix::Matrix(const int noOfRowss, const int noOfCols, double defaultValue)
{
this->noOfRows=noOfRowss;
this->noOfColums=noOfCols;
data= new double[noOfRows*noOfColumns];
for(int i=0; i< noOfRows; i++){
for(int j=0; j<noOfColumns; j++){
int index = i*noOfColumns + j;
data[index]=defaultValue;
}
}
}
在头文件中,可以有:
class Matrix
{
public:
Matrix(const int noOfRowss, const int noOfCols, double defaultValue = 0);
...
};
然后:
std::cout << Matrix(4,2) << std::endl; // displays a 4x2 matrix filled with zeros
std::cout << Matrix(4,2,1) << std::endl; // displays a 4x2 matrix filled with ones