重载运算符 [] 用于从对象数组中给出特定索引

overload operator [] to give a specific index from array of objects

本文关键字:索引 数组 对象 运算符 用于 重载      更新时间:2023-10-16

我有类XOBoard,它呈现了一个大小为 n*n 的数组,数组的每个单元格都是一个名为Cell的对象。

每个 Cell 对象由

class Cell {
private:
char ch;
public:
Cell(char ch = '.');
char getCellValue();
void setCellValue(char nch);
};

董事会的定义是这样的:

class XOBoard {
private:
int n;
Cell **Board;
};
XOBoard::XOBoard(int n) { //constructor
this->n = (n >= 3) ? n : 3;
Board = new Cell*[n];
for (int i = 0; i < n; i++) {
Board[i] = new Cell[n];
}
}

我想使用此方法获取特定的 Cell 值:board1[{1,2}],但我想检查发送给我的值是否在范围 (n( 内,但不幸的是我无法进入 Board 数组,并n变量。

这是代码:

XOBoard& operator[](list<int> list){
int x = list.front(), y = list.back();
return Board[x][y].getCellValue();
}

谢谢头!

如注释中所述,使用operator[]进行多维下标是非常规的,但如果需要,则应确保获得正确数量的值(在本例中为 2(并返回正确的类型(在本例中为Cell&(。

还要注意阴影。如果您尝试构造值小于 3 的Board,则将this->n设置为 3,但继续使用错误的n(甚至可能是负值(进行构造。

更多内联评论:

#include <iostream>
#include <stdexcept>
#include <tuple>
class Cell {
private:
char ch;
public:
Cell(char nch = '.') : // after the colon comes the member initializer list
ch(nch)            // which is usually good to use
{
// if(ch is not valid) throw ...
}
char getCellValue() const { return ch; }
// a convenient conversion operator to automatically
// convert a Cell to a char where a char is needed
// (like when streaming a Cell to std::cout)
operator char() const { return ch; }
// void setCellValue(char nch); // replaced by operator=
Cell& operator=(char nch) {
// if(nch is not valid) throw ...
ch = nch;
return *this;
}
};
class XOBoard {
private:
size_t n;       // use an unsigned type for sizes/indices
Cell** Board;
public:
// constructor
XOBoard(size_t xy_size) :          // a member initializer list again
n(xy_size >= 3 ? xy_size : 3), // assign to "n" here
Board(new Cell*[n])            // the correct n is now used
{
// if the below construction fails, a bad_alloc will be thrown.
// you need to add code to clean up what you've already allocated to take
// care of that situation.
for(size_t i = 0; i < n; i++) {
Board[i] = new Cell[n];
}
}
// Copying or moving need careful handling of the pointers.
// Read "The rule of three/five/zero". Until then, disable it.
XOBoard(const XOBoard&) = delete;
XOBoard& operator=(const XOBoard&) = delete;
// destructor
~XOBoard() {
for(size_t i = 0; i < n; i++) delete[] Board[i];
delete[] Board;
}
// added for convenience
size_t size() const { return n; }
// return a Cell& and use a std::pair since you
// expect exactly 2 values
Cell& operator[](std::pair<size_t, size_t> pos) {
auto& [x, y] = pos;
if(x>=n || y>=n)
throw std::out_of_range("{"+std::to_string(x)+","+std::to_string(y)+"}");
return Board[x][y];
}
};
int main() {
try {
XOBoard a{2};                   // trying an invalid size
std::cout << a.size() << 'n';
a[{2, 2}] = 'a';
std::cout << a[{2, 2}] << 'n';
Cell x = 'b';
a[{2, 2}] = x;
std::cout << a[{2, 2}] << 'n';
a[{2, 3}] = 'c';                // index out of bounds
} catch(const std::out_of_range& ex) {
std::cerr << "out_of_range exception: " << ex.what() << 'n';
}
}

输出:

3
a
b
out_of_range exception: {2,3}

您应该尽量避免使用原始指针和实际的多维数组。通常,最好通过分配一维数组来模拟维度,并为用户提供一个接口来计算要处理的正确元素。