使用括号运算符实现矩阵类的安全方法

时间:2018-01-17 09:16:00

标签: c++ operator-overloading

我正在编写一个二维矩阵类,只是为了它,包装矢量矢量。

由于矩阵必须具有正尺寸,我确保矩阵不能构造错误,从那时起我假设矩阵至少有一个元素:

"content": {
                "type": "text",
                "index": "true",
                "store": true
            }

我希望通过使用连接的Matrix2D::Matrix2D(size_t rows, size_t cols) { if (rows == 0 || cols == 0) { throw std::invalid_argument("Matrix cannot have zero as dimension"); } ... (即[])为用户提供访问和修改特定元素的方法。但是,我不希望用户能够修改矩阵的维度或修改一行中的列数。我目前提供如下所示的重载m[1][1]的方法是不够的,因为用户可以使用非const版本(修改特定元素所必需的)来修改列数:

operator[]

执行std::vector<double>& operator[](size_t r); const std::vector<double>& operator[](size_t r) const;

有没有办法在保持双括号格式的同时防止这种垮台?

我知道我可以像m[0] = std::vector<double>(0)一样使用operator(),但我对尝试使用双括号语法感到好奇。

3 个答案:

答案 0 :(得分:2)

您的operator[]可以返回定义了operator[]的代理对象。像这样:

class Matrix2D
{
  std::vector<std::vector<double>> rows;

  class Proxy
  {
    friend class Matrix2D;

    std::vector<double> &v;

    Proxy(std::vector<double> &v) : v(v) {}

  public:
    double& operator[] (size_t c) const { return p[c]; }
  };

public:
  Proxy operator[] (size_t r)
  {
    return { rows[r]; }
  }
};

但请注意,使用向量矢量来表示2D矩阵通常是一个坏主意,因为它非常缓存不友好。如果您只存储一个std::vector<double>大小rows * cols并手动索引,那么它将更接近实际可用性。

答案 1 :(得分:2)

我们的想法是让Matrix::operator[](size_t)返回一个代理对象,其operator[](size_t)返回对矩阵元素的(const)引用。

//untested
template<class T>
class Matrix
{
public:
    using value_type = T;

private:
    std::vector<value_type> _data;
    class Row
    {
        Matrix& _m;
        size_t  _row;
    public:
        Row(Matrix& m, size_t row) : _m(m), _row(row) {}
        value_type& operator[](size_t col) { return _m.at(_row, col); }
    }

public:
    // constructor(s) here
    value_type& at(size_t row, size_t col) { return /*...*/; }
    Row operator[](size_t row) { return Row{*this, row}; }
}

要添加:const版本,构造函数,索引,维度处理。完成后,您将能够像这样使用它:

Matrix<double> m{/*...*/};
m[1][2] = 28;
auto row = m[1];
row[1] = 18;
//row = std::vector<double>(0); // ERROR

答案 2 :(得分:0)

Peter Gottschling在他的出色著作《发现现代C ++》(Addison Wesley 2016)中展示了Matrix[][]的模板解决方案。他的方法使用了上面的代理类,另外还使用了奇怪的重复模板模式(CRTP)。