【问题标题】:operator overloading [][] 2d array c++运算符重载 [][] 二维数组 C++
【发布时间】:2016-03-31 09:47:09
【问题描述】:

我有一个二维数组,我想定义一个函数,该函数返回用户使用运算符重载给我的索引值。 换句话说:

void MyMatrix::ReturnValue()
{
    int row = 0, col = 0;
    cout << "Return Value From the last Matrix" << endl;
    cout << "----------------------------------" << endl;
    cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}

操作((*this).matrix)[row][col] 应该返回一个int。 我不知道如何构建operator [][]
或者,我可以连接几个对operator [] 的调用,但我没有成功,因为对该操作符的第一次调用将返回int*,第二次调用将返回int,它迫使建立另一个运营商,我不想这样做。

数据矩阵定义如下

int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
    cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
    matrix[i] = new int[col];
    if (matrix[i] == NULL)
    {
        cout << "Allocation memory - Failed";
        return;
    }
}

我能做什么? 谢谢,

【问题讨论】:

  • 简单地说,such an operator does not exist,所以你不能超载它。
  • 好的,这意味着我必须为运算符 [] 构建两个函数,因为如果我这样做:(((*this).matrix)[row])[col] 那么第一个运算符将返回 int* 和第二个 int。跨度>
  • @lilach 显示数据成员矩阵是如何定义的。
  • int** matrix; matrix = new int*[row]; if (matrix == NULL) { cout &lt;&lt; "Allocation memory - Failed"; } for (int i = 0; i &lt; row; i++)//Allocation memory { matrix[i] = new int[col]; if (matrix[i] == NULL) { cout &lt;&lt; "Allocation memory - Failed"; return; } }

标签: c++ arrays operator-overloading 2d operator-keyword


【解决方案1】:

简单地说,such an operator does not exist,所以你不能超载它。

一种可能的解决方案是定义两个类:MatrixRow
您可以定义Matrixoperator[],使其返回Row,然后为Row 定义相同的运算符,使其返回实际值(int 或任何您想要的,您的@987654329 @ 也可以是模板)。
这样,myMatrix[row][col] 的声明就合法且有意义。

同样可以将新的Row 分配给Matrix 或更改Row 中的值。

* 编辑 *

根据 cmets 中的建议,在这种情况下,您也应该 take in consideration 使用 operator() 而不是 operator[]
这样,就不再需要 Row 类了。

【讨论】:

  • 我还要提一下,重载运算符() 是一种更简单的方法,它重载[] 以返回一些带有自己的运算符[] 的自定义类。见the C++ FAQs on this respect
  • 当然,这是有道理的,但我知道 OP 的目标是使用像 myMatrix[row][col] 这样的语句,这就是为什么我继续使用使用 operator[] 的解决方案。无论如何,好的提示,我将修改响应。
  • LINKER如何区分ROW和Matrix的功能。都得到int。他们有相同的签名。运算符第一次获得索引行并返回指向该行的指针(int),而不是获得索引col(int)
  • @lilach 对,但它们属于不同的类。 :-)
  • const int MyMatrix::operator[](const int index)constconst int* Row::operator[](const int index)const
【解决方案2】:

您可以为班级定义自己的operator []。一个简单的方法可以如下所示

#include <iostream>
#include <iomanip>

struct A
{
    enum { Rows = 3, Cols = 4 };
    int matrix[Rows][Cols];
    int ( & operator []( size_t i ) )[Cols]
    {
        return matrix[i];
    }
};

int main()
{
    A a;

    for ( size_t i = 0; i < a.Rows; i++ )
    {
        for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
    }


    for ( size_t i = 0; i < a.Rows; i++ )
    {
        for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
        std::cout << std::endl;
    }
}

程序输出是

 0  1  2  3 
 4  5  6  7 
 8  9 10 11 

【讨论】:

  • 赞成,尽管他的同事看到这个接线员肯定会伤害他。 :-) ...我仍在试图弄清楚它是如何以及为什么起作用的!谢谢你,给我求知欲的圣诞礼物。
  • 之所以有效,是因为它返回对数组中选定行的引用,然后可以使用[] 进一步对其进行索引-该类型为int &amp; [Cols],这是@987654326 的真实结果类型@ 在它衰减为指针之前。然而,返回这样一个引用的函数的语法丑陋且令人困惑,在同一个成员函数指针联盟中,所以大多数人不理会它,只是返回一个指向相关行的第一个元素的指针。跨度>
  • 虽然我很欣赏这里和那里的 WAT,但我建议使用尾随返回类型
  • @lilach matrix[i] 返回对一维数组的引用。因此,您可以再次应用 operator [] 以获得整数。那就是这条记录 a[i][j] 将是有效的。
  • @lilach 为了使定义更简单,您可以为返回类型引入 using 别名或类型 def。例如 struct A { enum { Rows = 3, Cols = 4 };使用 TRow = int ( & )[Cols];整数矩阵[行][列]; TRow 运算符 []( size_t i ) { 返回矩阵 [i]; } };
【解决方案3】:

我不知道如何构建operator [][]

有时可以使用不同的运算符,即()

int& Matrix::operator () (int x, int y)
{
    return matrix[x][y];
}

const int& Matrix::operator () (int x, int y) const
{
    return matrix[x][y];
}

int diagonal (const Matrix& m, int x)
{
    return m (x, x); // Usage.
}

优势

  • 无需使用像RowColumn 这样的“中级”类。

  • Row&amp; Matrix operator (int); 更好的控制,因为有人可以使用Row 引用来插入一行非法长度。如果Matrix 应该代表一个矩形的东西(图像,代数中的矩阵),那是一个潜在的错误来源。

  • 在较高维度上可能不那么乏味,因为operator[] 需要所有较低维度的类。

缺点:

  • 不常见,不同的语法。

  • 如果需要,无需再轻松替换完整的行/列。但是,无论如何,替换列并不容易,只要您使用行来建模(反之亦然)。

在任何一种情况下,如果在运行时不知道维数,则各有利弊。

【讨论】:

    【解决方案4】:

    我正在寻找自测阵列替换... 改进版本返回引用或空引用并检查内部边界。

    #include <iostream>
    #include <iomanip>
    
    template<typename T, int cols>
    class Arr1
    {
    public:
        Arr1(T (&place)[cols]) : me(place) {};
        const size_t &Cols = cols;
        T &operator [](size_t i)
        {
            if (i < cols && this != NULL) return me[i];
            else {
                printf("Out of bounds !\n");
                T *crash = NULL;
                return *crash;
            }
        }
    private:
        T (&me)[cols];
    };
    template<typename T, int rows, int cols>
    class Arr2
    {
    public:
        const size_t &Rows = rows;
        const size_t &Cols = cols;
        Arr2() {
            ret = NULL;
            for (size_t i = 0; i < rows; i++) // demo - fill member array
            {
                for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
            }
        }
        ~Arr2() {
            if (ret) delete ret;
        }
        Arr1<T, cols>(&operator [](size_t i))
        {
            if (ret != NULL) delete ret;
            if (i < rows) {
                ret = new Arr1<T, cols>(matrix[i]);
                return *ret;
            }
            else {
                ret = NULL;
                printf("Out of bounds !\n");
                return *ret;
            }
        }
        //T(&MemberCheck)[rows][cols] = matrix;
    private:
        T matrix[rows][cols];
        Arr1<T, cols> *ret;
    };
    template<typename T,int rows, int cols>
    class Arr
    {
    public:
        const size_t &Rows = rows;
        const size_t &Cols = cols;
        T(&operator [](size_t i))[cols]
        {
            if (i < rows) return matrix[i];
            else {
                printf("Out of bounds !\n");
                T(*crash)[cols] = NULL;
                return *crash;
            }
        }
        T (&MemberCheck)[rows][cols] = matrix;
    private:
        T matrix[rows][cols];
    };
    
    void main2()
    {
        std::cout << "Single object version:" << endl;
        Arr<int, 3, 4> a;
    
        for (size_t i = 0; i <= a.Rows; i++)
        {
            int *x = &a[i][0];
            if (!x) printf("Fill loop - %i out of bounds...\n", i);
            else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
        }
    
        for (size_t i = 0; i < a.Rows; i++)
        {
            for (size_t j = 0; j <= a.Cols; j++) {
                std::cout << std::setw(2) << a[i][j] << ' ';
                if (a.MemberCheck[i][j] != a[i][j])
                    printf("Internal error !");
            }
            std::cout << std::endl;
        }
    
        std::cout << endl << "Double object version:" << endl;
    
        Arr2<int, 3, 4> a2;
        for (size_t i = 0; i < a2.Rows; i++)
        {
            for (size_t j = 0; j <= a2.Cols; j++) {
                int &x = a2[i][j];
                if (&x)
                {
                    x++;
                    std::cout << std::setw(2) << a2[i][j] << ' ';
                    //if (&a2.MemberCheck[i][j] != &a2[i][j])
                    //  printf("Internal error !");
                }
            }
        }
    }
    

    输出

    Single object version:
    Out of bounds !
    Fill loop - 3 out of bounds...
     0  1  2  3  4
     4  5  6  7  8
     8  9 10 11 -858993460
    
    Double object version:
     1  2  3  4 Out of bounds !
     5  6  7  8 Out of bounds !
     9 10 11 12 Out of bounds !
    

    【讨论】:

      【解决方案5】:
      #include<iostream>
      using namespace std;
      class matrix
      {
           int **arr;
           int r;
           int c;
           public:
          /* another code*/
           class row
          {
              matrix &_a;
              int _i;
              public:
              row(matrix &a,int i) : _a(a),_i(i){}
              int operator[](int j) {return _a.arr[_i][j];}
           };
           row operator[](int i)
          {   
              return row(*this,i);
           }
       };
      

      这对你有帮助

      【讨论】:

      • 您通常不应该只用代码回答问题。相反,您还应该解释为什么代码有效以及什么想法/技术/等。被使用。
      猜你喜欢
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      • 2012-03-24
      • 2016-08-30
      相关资源
      最近更新 更多