【问题标题】:C++ operator overloading fails to output + operationC++运算符重载失败输出+运算
【发布时间】:2021-07-01 18:51:38
【问题描述】:

我正在学习 C++ 并尝试为矩阵编写 C++ 类,我将矩阵存储为一维 C 数组。为此,我定义了一个element 成员函数来根据矩阵元素在数组中的位置来访问它们。然后我重载了<<+ 运算符来处理矩阵的显示和添加。 << 运算符按预期工作,如下例所示:

#include<iostream>

class matrix {
    friend std::ostream & operator<<(std::ostream &os, matrix &M);
private:
    int rows{}, columns{};
    double *array {nullptr};
public:
    matrix(int rows, int columns);
    ~matrix() {}

    double & element(int r, int c);

    matrix operator+(matrix &M)
    {
        matrix N(rows, columns);
        if (M.rows!=rows || M.columns!=columns){
            std::cout << "ERROR: DIMENSIONS OF MATRICES DO NOT MATCH" << std::endl;
        }
        else{
            for (int i{1}; i<=M.rows; i++)
            for (int j{1}; j<=M.columns; j++){
                N.element(i,j) = element(i,j) + M.element(i,j);
            }
        }
        return N;
    }
};

matrix::matrix(int r, int c)
{
    rows = r;
    columns = c;
    array = new double[rows*columns];
    for(int i{0}; i<rows*columns; i++) array[i]=0.0;
}

double & matrix::element(int i, int j)
{
    int loc{0};
    loc = (j-1) + (i-1)*columns;
    return array[loc];
}

std::ostream & operator<<(std::ostream &os, matrix &M)
{
    for (int i{1}; i<=M.rows; i++){
        os << "[ ";
        for (int j{1}; j<=M.columns; j++){
            os << M.element(i,j) << " "; 
        }
        os << "] \n";
    }
    return os;
}


int main() {
    matrix A(2,2);
    matrix B(2,2);
    A.element(1,1) = 1;
    A.element(1,2) = 2;
    A.element(2,1) = 3;
    A.element(2,2) = 4;
    B.element(1,1) = 1;
    B.element(1,2) = 2;
    B.element(2,1) = 3;
    B.element(2,2) = 4;
    std::cout << A << std::endl;
    std::cout << B << std::endl;

    return 0;
}

然后我无法显示两个矩阵的相加:

    std::cout << A+B << std::endl;

但是,如果我在显示它们的总和之前分解运算并分别添加矩阵,我会得到正确的输出,这让我相信 + 运算符也可以正常工作:

    matrix C(2,2);
    C = A+B;
    std::cout << C << std::endl;

该错误似乎表明将矩阵元素转换为 ostream 可能存在问题,但奇怪的是上述解决方法是否有效。

【问题讨论】:

  • 对您的代码的注释,与您的问题无关:为array 使用智能指针,那么您不需要析构函数。不要使用new/delete,除非你想了解c++的内部工作原理。真的很容易把事情搞砸。

标签: c++ class matrix operator-overloading ostream


【解决方案1】:

您的 &lt;&lt; 运算符将非常量引用作为参数对矩阵进行引用。这意味着它不能引用临时对象。 A+B 的结果是一个临时对象,如果你不将它分配给某个东西。

所以你需要改变这个:

std::ostream & operator<<(std::ostream &os, matrix &M);

进入这个:

std::ostream & operator<<(std::ostream &os, const matrix &M);

您的+-operator 迟早会遇到同样的问题:

matrix operator+(matrix &M)

应该是

// Both `M` and `*this` should be const
matrix operator+(const matrix &M) const

你的 element 方法自然会出现问题,它只能作用于非常量对象,因此你还需要一个作用于 const 对象的变体:

class matrix
{
   ....
 public:
   double & element(int r, int c);
   double element(int r, int c) const;
   ...
}

【讨论】:

    【解决方案2】:

    您不能对临时对象进行非const 引用。您尝试使用临时 (A+B) 调用 operator&lt;&lt;,但重载的 operator&lt;&lt; 的签名采用非 const 引用,因此您的函数不是有效的候选者。

    要解决此问题,您需要进行一些更改。首先,让您重载的&lt;&lt; 运算符采用const 对矩阵的引用。并且不要忘记修复类声明中的friend 签名。

    std::ostream & operator<<(std::ostream &os, const matrix &M);
    

    这样做仍然会导致错误,因为element 方法只为非const 对象定义。您需要为element 添加一个作用于const matrixes 的重载(并且不允许您修改返回的元素)。

    double matrix::element(int i, int j) const
    {
        int loc = (j-1) + (i-1)*columns;
        return array[loc];
    }
    

    【讨论】:

    • const 版本的element() 也可以只返回double 而不是const double&amp;
    【解决方案3】:

    您的operator&lt;&lt;operator+ 都需要通过const 引用获取输入matrix,以便它们可以接受临时matrix 对象作为输入。

    另外,operator+ 应该是const-qualified,因为它不会修改this 的内容。并且element() 应该有一个const 限定的重载,因此它可以提供对const matrix 对象的只读访问。

    根据Rule of 3/5/0,您还缺少一个复制构造函数、一个复制赋值运算符、一个移动构造函数和一个移动赋值运算符。而且,你的析构函数根本没有释放 C 数组,所以它被泄露了。

    试试这个:

    #include <iostream>
    #include <stdexcept>
    #include <utility>
    
    class matrix {
        friend std::ostream& operator<<(std::ostream &os, const matrix &M);
    private:
        int rows{}, columns{};
        double* array{nullptr};
    public:
        matrix(int rows, int columns);
        matrix(const matrix &M);
        matrix(matrix &&M);
        ~matrix();
    
        matrix& operator=(matrix M);
    
        double& element(int r, int c);
        double element(int r, int c) const;
    
        matrix operator+(const matrix &M) const;
        matrix& operator+=(const matrix &M);
    };
    
    matrix::matrix(int r, int c)
        : rows(r), columns(c)
    {
        size_t size = rows*columns;
        array = new double[size];
        for(size_t i = 0; i < size; ++i)
            array[i] = 0.0;
    }
    
    matrix::matrix(const matrix &M)
        : rows(M.rows), columns(M.columns)
    {
        size_t size = rows*columns;
        array = new double[size];
        for(size_t i = 0; i < size; ++i)
            array[i] = M.array[i];
    }
    
    matrix::matrix(matrix &&M)
        : rows(M.rows), columns(M.columns), array(M.array)
    {
        M.rows = M.columns = 0;
        M.array = nullptr;
    }
    
    matrix::~matrix()
    {
        delete[] array;
    }
    
    matrix& operator=(matrix M)
    {
        std::swap(rows, M.rows);
        std::swap(columns, M.columns);
        std::swap(array, M.array);
        return *this;
    }
    
    double& matrix::element(int r, int c)
    {
        // TODO: do bounds checking here...
        size_t loc = ((r-1)*columns) + (c-1);
        return array[loc];
    }
    
    double matrix::element(int r, int c) const
    {
        // TODO: do bounds checking here...
        size_t loc = ((r-1)*columns) + (c-1);
        return array[loc];
    }
    
    std::ostream & operator<<(std::ostream &os, const matrix &M)
    {
        for (int r = 1; r <= M.rows; ++r){
            os << "[ ";
            for (int c = 1; c <= M.columns; ++c){
                os << M.element(r,c) << " "; 
            }
            os << "]\n";
        }
    
        /* alternatively...
        size_t loc = 0;
        for (int r = 0; r < M.rows; ++r){
            os << "[ ";
            for (int c = 0; c < M.columns; ++c){
                os << M.array[loc++] << " ";
            }
            os << "]\n";
        }
        */
    
        return os;
    }
    
    matrix matrix::operator+(const matrix &M) const
    {
        matrix N(*this);
        N += M;
        return N;
    }
    
    matrix& matrix::operator+=(const matrix &M)
    {
        if (M.rows != rows || M.columns != columns){
            throw std::runtime_error("DIMENSIONS OF MATRICES DO NOT MATCH");
        }
    
        for (int r = 1; r <= rows; ++r)
            for (int c = 1; c <= columns; ++c){
                element(r,c) += M.element(r,c);
            }
        }
    
        /* alternatively:
        size_t size = rows*columns;
        for (size_t i = 0; i < size; ++i)
            array[i] += M.array[i];
        }
        */
    
        return *this;
    }
    
    int main() {
        matrix A(2,2);
        matrix B(2,2);
        A.element(1,1) = 1;
        A.element(1,2) = 2;
        A.element(2,1) = 3;
        A.element(2,2) = 4;
        B.element(1,1) = 1;
        B.element(1,2) = 2;
        B.element(2,1) = 3;
        B.element(2,2) = 4;
        std::cout << A << std::endl;
        std::cout << B << std::endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2013-12-15
      • 2012-12-30
      相关资源
      最近更新 更多