代码之家  ›  专栏  ›  技术社区  ›  Ashish

如何为二维数组的包装类重载数组索引运算符?

  •  6
  • Ashish  · 技术社区  · 15 年前
    #define ROW 3
    #define COL 4
    
    class Matrix
    {
       private:
          int mat[ROW][COL];  
        //.....
        //.....
    
    };
    
    int main()
    {
      Matrix m;
      int a = m[0][1]; //  reading
      m[0][2] = m[1][1]; // writing
    } 
    

    我认为直接超载是不可能的。

    我想我必须间接地去做,但是如何实现呢?

    2 回复  |  直到 15 年前
        1
  •  10
  •   Loki Astari    15 年前

    更简单的解决方案是使用operator(),因为它允许多个参数。

    class M
    {
        public:
           int& operator()(int x,int y)  {return at(x,y);}
        // .. Stuff to hold data and implement at()
    };
    
    
    M   a;
    a(1,2) = 4;
    

    简单的方法是,第一个运算符[]返回中间对象,第二个运算符[]返回数组中的值。

    class M
    {
        public:
        class R
        {
             private:
                 friend class M; // Only M can create these objects.
                 R(M& parent,int row): m_parent(parent),m_row(row) {}
             public:
                  int& operator[](int col) {return m_parent.at(m_row,col);}
             private:
                  M&  m_parent;
                  int m_row;
        };
    
        R operator[](int row) {return R(*this,row);}
    
        // .. Stuff to hold data and implement at()
    };
    
    M   b;
    b[1][2] = 3;   // This is shorthand for:
    
    R    row = b[1];
    int& val = row[2];
    val      = 3;
    
        2
  •  1
  •   sellibitze    15 年前

    由于您希望将元素存储在固定大小的数组中,因此相当容易:

    #define ROWS 3
    #define COLS 4
    
    typedef int row_type[COLS];
    
    class matrix {
       row_type elements[ROWS];
    public:
       ...
       row_type const& operator[](int r) const {return elements[r];}
       row_type      & operator[](int r)       {return elements[r];}
       ...
    };
    

    那应该管用。

    此外,您可能需要替换 #define 使用适当的常量,或使用模板参数进行类型(int)和大小(3x4)以使矩阵类更通用。如果要支持动态大小,则运算符[]需要返回代理对象。这是可能的,但对于元素访问,您可能更喜欢使用带有两个索引参数的operator()。