如何使用静态成员函数创建矩阵,然后使用运算符重载打印该矩阵

How to use a static member function to create a matrix which can then be printed using operator overloading?

本文关键字:运算符 重载 打印 静态成员 何使用 函数 创建 然后      更新时间:2023-10-16

使用构造函数和运算符重载的工作原理如下,我的目标是创建一个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;

我需要保留数据变量的原因是,它可以用于运算符<lt;重载函数,就像它以前为构造函数所做的那样。然而,在我的静态成员函数中尝试了几种不同的变体后,我没有像以前那样容易地将矩阵存储在数据变量中。有人有什么建议吗?

因此,我看到您的静态函数显然首先做到了这一点。

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

然后,在没有有效初始化的data成员的情况下,尝试初始化默认构造矩阵的内容。

这不会有好的结局。。。

附言,你可能也想读一读:RAII。我怀疑你们班在这方面也会有相关的问题。与其使用double *data成员,std::vector<double>将更好地工作,并且很可能避免该领域的一系列陷阱。

您需要像这样psecify 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;
        }
    }
}

如果这样做,至少遵循三条规则会更安全,因为使用Matrix::Zeros很可能会在代码中通过复制进行构造或通过复制进行赋值(如果定义不正确,会导致更多的segfault,使用默认实现的编译器会导致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