58

我可以在 C++ 中定义一个接受多个参数的数组运算符吗?我试过这样:

const T& operator[](const int i, const int j, const int k) const{ 
    return m_cells[k*m_resSqr+j*m_res+i];
}

T& operator[](const int i, const int j, const int k){ 
    return m_cells[k*m_resSqr+j*m_res+i];       
}

但我收到了这个错误:

error C2804 binary operator '[' has too many parameters
4

6 回答 6

56

不,您不能重载operator[]以接受多个参数。相反,您可以重载operator(). 请参阅如何为 Matrix 类创建下标运算符?来自 C++ 常见问题解答。

于 2009-12-20T17:25:56.860 回答
46

不可能重载[]运算符以接受多个参数,但另一种方法是使用代理模式

用两个词:a[x][y],第一个表达式 ( a[x]) 将返回一个不同的类型,命名为代理类型,它会有另一个operator[]. 它会调用类似于_storedReferenceToOriginalObject->At(x,y)原始类的东西。

你将无法做到a[x,y],但我想你还是想重载通常的 C++ 风格的 2D 数组语法。

于 2009-12-20T17:31:26.560 回答
43

您可以使用 C++11 中可用的统一初始化语法来做一个很好的小技巧。您无需直接获取索引,而是使用 POD。

struct indices
{
  std::size_t i, j, k;
};

T& operator[](indices idx)
{
  return m_cells[idx.k * m_resSqr + idx.j * m_res + idx.i];
}

然后使用新语法:

my_array<int> arr;
// ...
arr[{1, 2, 3}] = 42;
于 2014-12-10T11:10:37.723 回答
15

为了完整起见:有一种方法可以实际使用带有多个参数的括号运算符,如果它们不是基本数据类型,即通过重载逗号运算符而不是括号运算符,请参阅以下有关逗号重载的帖子:

https://stackoverflow.com/a/18136340/5836981

免责声明:在我看来,重载逗号运算符容易出错并使代码更加晦涩难懂,只有在更奇特的情况下才值得考虑。我添加了这个答案,因为我在一些代码中遇到了这个实例,我花了一段时间才弄清楚关键不是 [] 运算符(不能用多个参数重载)而是 , 运算符。

于 2017-02-02T17:52:07.453 回答
1

C++ 中任意类型和大小的 N 维数组:

这个答案的灵感来自 Pavel Radzivilovsky 的答案,谢谢。我很难实现实现,因为这是我第一次尝试递归模板。我想分享我所做的事情,以便其他人可以比我更快地理解。

我编写了一个 c++ 模板类来创建一个任意类型和大小的 n 维数组。它需要用数组类型和维数来实例化。大小可以动态更改。我在下面给出了如何创建一个多维数组的裸(剥离)工作版本,其元素可以通过连续应用运算符[](例如数组[x][y][z])来访问。这个版本只能处理维度 n>1 的数组。main 函数以如何创建一个 4 维整数数组为例。

编辑:请记住,下面的示例对于可读性来说是最小的,因为它不会取消分配数组,也不会对访问进行边界检查。添加它是微不足道的,并留给程序员。

#include <stdio.h>
#include <stdlib.h>

template <typename T, int N>
struct array {
    array<T,N>() : data(NULL), offset((int*) malloc(sizeof(int)*N)){}
    array<T,N>(T *data, int *offset) : data(data), offset(offset){}
    array<T,N-1> operator[](int i){return array<T,N-1>(&data[i*offset[N]], offset);}
    bool resize(int *size){
        offset[N-1] = 1;
        int total_size = size[N-1];
        for(int i = N-2; i >= 0; i--){
            total_size *= size[i];
            offset[i] = offset[i+1]*size[i+1];
        }
        return (data = (T*) realloc (data, total_size*sizeof(T)));
    }
    T *data;
    int *offset;
};

template <typename T>
struct array<T,1>{
    array<T,1>(T *data, int *offset) : data(data){}
    T& operator[](int i){return data[i];}
    T *data;
};

int main () {
    array<int, 4> a;

    // create array with dimensions [1][3][3][7]
    int size[4] = { 1, 3, 3, 7 };
    a.resize(size);               

    a[0][1][2][3] = 123;

    return 0;
}

享受。

于 2014-08-13T14:28:49.710 回答
1

编辑:正如评论中所指出的,在C++20中,运算符逗号将被弃用,如下面的答案。

你不能重载operator[],但你可以通过重载来伪造它operator,

按照您的代码,它变为:

T& operator,(const int i, const int j, const int k){ 
    return m_cells[k*m_resSqr+j*m_res+i];       
}

现在你可以打电话了

something[1, 2, 3]

您可以使用模板、带有可变参数的模板std::pairstd::tuple根据您的用例和 C++ 版本来扩展它

于 2020-01-16T16:52:07.687 回答