在 c++ 中为类创建 [][] 运算符

Creating [][] operator for class in c++

本文关键字:运算符 创建 c++      更新时间:2023-10-16

我正在为某人制作一个 Pentago 游戏,我想写一个好的代码,所以我决定使用运算符重载。

我们有 2 个类;第一个是块类(代表电路板的每个块(,第二个是 Set 类(代表 3*3 块表(。现在我想将 Set 用作 2d 数组,以便我可以使用 set[foo][foo]。你能帮我做一个这样的运算符吗?

一个非常简单的解决方案是

struct MyClass {
    int x[3][3];
    int* operator[](int row) { return &(x[row][0]); }
};

即从operator[]返回element*

这允许使用

myinstance[row][col]

(至少(有两种方法可以去这里。


首先是制作类似 set_row 类的东西,这是一个代理。所以你会有类似的东西

class set
{
public:
    set_row operator[](size_t row)
    {
        // Return a proxy object that just sees the correct row.
        return set_row(internal_buffer_pointer[row]);
    }
    ...
};

set_row是这样的

class set_row
{
public:
     // Ctor takes a row
     // Take a column, and return a reference to the correct column in the row.
     element &operator[](size_t column);
};

根据经验(on,咳咳,VisualC ++(,这很慢,因为它需要为每个访问构造一个代理对象。


二是放弃operator[],使用operator()

class set
{
public:
    element &operator()(size_t row, size_t col);

    ...
};

使用operator[]会很好,但不幸的是,你不能用它做到这一点。

没有operator[][] .如果要提供这些语义,则需要重载operator[]以便它返回另一个也重载operator[]的对象。

您的案例可以使用向量向量来解决

#include <vector>
#include <cstdint>
#include <iostream>
struct Block
{
    int value = 0;
};
class Set
{
    std::vector<std::vector<Block> > grid;
public:
    Set(): grid(3, std::vector<Block>(3)) {} // 3 x 3
    std::vector<Block>& operator[](std::size_t x) { return grid[x]; }
};
int main()
{
    using std::size_t;
    Set set;
    set[1][1].value = 1;
    for(size_t x = 0; x < 3; ++x)
    {
        for(size_t y = 0; y < 3; ++y)
        {
            std::cout << set[x][y].value << ' ';
        }
        std::cout << 'n';
    }
}

输出:

0 0 0 
0 1 0 
0 0 0 

这是有效的,因为Set::operator[]返回对std::vector的引用,并且std::vector重载operator[]返回对Block的引用。

无法为类提供operator[][]

但是,如果您的Set提供operator[](),则该运算符可以返回对其他具有operator[]()的引用。

例如;

 class Row
 {
      public:
           Block &operator[](int block_no) {return data[block_no];};
      private:
           std::vector<Block> data;
 };
 class Set
 {
       public:
          Row &operator[](int row_no) {return row[row_no];};
       private:
           std::vector<Row> row;
 };
 int main()
 {
     Set s;
       // assume s is set up appropriately
     Block b = s[2][3];    //  equivalent to s.operator[](2).operator[](3)
 }

显然,还需要进行相关的错误检查,正确设置类的内容等。

假设内存是连续的,则可以返回指向行的第一个元素的指针。

工作示例

#include <iostream>
class MyType
{
public:
    static const size_t rows = 3;
    static const size_t columns = 3;
    static const size_t size = rows * columns;
    MyType()
    {
        for(size_t index = 0; index < 9; ++index)
        {
            data[index] = index;
        }
    }
    int* operator[](size_t index)
    {
        return &data[rows * index];
    }
private:
    int data[size];
};
int main()
{
    MyType instance;
    std::cout << instance[2][1] << std::endl;
}