C++ 运算符[][] 重载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6969881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:02:52  来源:igfitidea点击:

Operator[][] overload

c++operator-overloading

提问by icepopo

Is it possible to overload []operator twice? To allow, something like this: function[3][3](like in a two dimensional array).

是否可以重载[]运算符两次?允许,像这样:(function[3][3]就像在二维数组中一样)。

If it is possible, I would like to see some example code.

如果可能的话,我想看看一些示例代码。

回答by Seth Carnegie

You can overload operator[]to return an object on which you can use operator[]again to get a result.

您可以重载operator[]以返回一个对象,您可以operator[]再次使用该对象来获取结果。

class ArrayOfArrays {
public:
    ArrayOfArrays() {
        _arrayofarrays = new int*[10];
        for(int i = 0; i < 10; ++i)
            _arrayofarrays[i] = new int[10];
    }

    class Proxy {
    public:
        Proxy(int* _array) : _array(_array) { }

        int operator[](int index) {
            return _array[index];
        }
    private:
        int* _array;
    };

    Proxy operator[](int index) {
        return Proxy(_arrayofarrays[index]);
    }

private:
    int** _arrayofarrays;
};

Then you can use it like:

然后你可以像这样使用它:

ArrayOfArrays aoa;
aoa[3][5];

This is just a simple example, you'd want to add a bunch of bounds checking and stuff, but you get the idea.

这只是一个简单的例子,你想添加一堆边界检查和东西,但你明白了。

回答by Lightness Races in Orbit

An expression x[y][z]requires that x[y]evaluates to an object dthat supports d[z].

表达式x[y][z]要求x[y]计算结果为d支持d[z].

This means that x[y]should be an object with an operator[]that evaluates to a "proxy object" that alsosupports an operator[].

这意味着x[y]应该是一个具有 的对象,该对象的operator[]计算结果为支持operator[].

This is the only way to chain them.

这是链接它们的唯一方法。

Alternatively, overload operator()to take multiple arguments, such that you might invoke myObject(x,y).

或者,重载operator()以接受多个参数,这样您就可以调用myObject(x,y).

回答by Bo Persson

For a two dimensional array, specifically, you might get away with a single operator[] overload that returns a pointer to the first element of each row.

具体而言,对于二维数组,您可能会避免使用单个 operator[] 重载,该重载返回指向每行第一个元素的指针。

Then you can use the built-in indexing operator to access each element within the row.

然后您可以使用内置索引运算符来访问行中的每个元素。

回答by John

It is possible if you return some kind of proxy class in first [] call. However, there is other option: you can overload operator() that can accept any number of arguments (function(3,3)).

如果您在第一个 [] 调用中返回某种代理类,则有可能。但是,还有其他选择:您可以重载可以接受任意数量参数 ( function(3,3)) 的operator( )。

回答by Ajay

One approach is using std::pair<int,int>:

一种方法是使用std::pair<int,int>

class Array2D
{
    int** m_p2dArray;
public:
    int operator[](const std::pair<int,int>& Index)
    {
       return m_p2dArray[Index.first][Index.second];
    }
};

int main()
{
    Array2D theArray;
    pair<int, int> theIndex(2,3);
    int nValue;
    nValue = theArray[theIndex];
}

Of course, you may typedefthe pair<int,int>

当然,您可以typedefpair<int,int>

回答by Node

You can use a proxy object, something like this:

您可以使用代理对象,如下所示:

#include <iostream>

struct Object
{
    struct Proxy
    {
        Object *mObj;
        int mI;

        Proxy(Object *obj, int i)
        : mObj(obj), mI(i)
        {
        }

        int operator[](int j)
        {
            return mI * j;
        }
    };

    Proxy operator[](int i)
    {
        return Proxy(this, i);
    }
};

int main()
{
    Object o;
    std::cout << o[2][3] << std::endl;
}

回答by neuront

It 'll be great if you can let me know what function, function[x]and function[x][y]are. But anyway let me consider it as an object declared somewhere like

这会是巨大的,如果你可以让我知道什么functionfunction[x]function[x][y]是。但无论如何让我将其视为在某处声明的对象

SomeClass function;

(Because you said that it's operator overload, I think you won't be interested at array like SomeClass function[16][32];)

(因为你说它是运算符重载,我想你不会对像这样的数组感兴趣SomeClass function[16][32];

So functionis an instance of type SomeClass. Then look up declaration of SomeClassfor the return type of operator[]overload, just like

functiontype 的实例也是如此SomeClass。然后查找重载SomeClass返回类型的 声明operator[],就像

ReturnType operator[](ParamType);

ReturnType operator[](ParamType);

Then function[x]will have the type ReturnType. Again look up ReturnTypefor the operator[]overload. If there is such a method, you could then use the expression function[x][y].

然后function[x]会有类型ReturnType。再次抬头ReturnTypeoperator[]过载。如果有这样的方法,那么您可以使用表达式function[x][y]

Note, unlike function(x, y), function[x][y]are 2 separate calls. So it's hard for compiler or runtime garantees the atomicity unless you use a lock in the context. A similar example is, libc says printfis atomic while successively calls to the overloaded operator<<in output stream are not. A statement like

请注意,与 不同的是function(x, y)function[x][y]是 2 个单独的调用。因此,除非您在上下文中使用锁,否则编译器或运行时很难保证原子性。一个类似的例子是,libc 说printf是原子的,而连续调用operator<<输出流中的重载则不是。像这样的声明

std::cout << "hello" << std::endl;

might have problem in multi-thread application, but something like

在多线程应用程序中可能有问题,但类似

printf("%s%s", "hello", "\n");

is fine.

很好。

回答by Kaustav Ray

#include<iostream>

using namespace std;

class Array 
{
     private: int *p;
     public:
          int length;
          Array(int size = 0): length(size)
          {
                p=new int(length);
          }
          int& operator [](const int k)
          {
               return p[k];
          }
};
class Matrix
{
      private: Array *p;
      public: 
            int r,c;
            Matrix(int i=0, int j=0):r(i), c(j)
            {
                 p= new Array[r];
            }
            Array& operator [](const int& i)
            {
                 return p[i];
            }
};

/*Driver program*/
int main()
{
    Matrix M1(3,3); /*for checking purpose*/
    M1[2][2]=5;
}

回答by Grandstack

struct test
{
    using array_reference = int(&)[32][32];

    array_reference operator [] (std::size_t index)
    {
        return m_data[index];
    }

private:

    int m_data[32][32][32];
};

Found my own simple solution to this.

找到了我自己的简单解决方案。

回答by Yakk - Adam Nevraumont

template<class F>
struct indexer_t{
  F f;
  template<class I>
  std::result_of_t<F const&(I)> operator[](I&&i)const{
    return f(std::forward<I>(i))1;
  }
};
template<class F>
indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}

This lets you take a lambda, and produce an indexer (with []support).

这使您可以使用 lambda,并生成索引器(有[]支持)。

Suppose you have an operator()that supports passing both coordinates at onxe as two arguments. Now writing [][]support is just:

假设您有一个operator()支持将 onxe 处的两个坐标作为两个参数传递。现在写作[][]支持只是:

auto operator[](size_t i){
  return as_indexer(
    [i,this](size_t j)->decltype(auto)
    {return (*this)(i,j);}
  );
}

auto operator[](size_t i)const{
  return as_indexer(
    [i,this](size_t j)->decltype(auto)
    {return (*this)(i,j);}
  );
}

And done. No custom class required.

并做了。不需要自定义类。