的基本思路看起来是这样的:
#include <vector>
#include <iostream>
template <class T>
class matrix {
size_t cols;
size_t rows;
std::vector<T> data;
class row_proxy { // This class is the part the question really asked about
size_t row;
matrix &m;
public:
row_proxy(matrix &m, size_t row) : row(row), m(m) {}
T &operator[](size_t col) {
if (row > m.rows || col > m.cols)
throw std::logic_error("Bad index");
return m.data[row * m.cols + col];
}
};
public:
matrix(size_t cols, size_t rows) : rows(rows), cols(cols), data(rows*cols) {}
row_proxy operator[](size_t row) {
return row_proxy(*this, row);
}
};
int main() {
matrix<int> m(3, 3);
for (int i=0; i<3; i++) // fill the matrix with identifiable numbers
for (int j=0; j<3; j++)
m[i][j] = i * 100 + j;
for (int i=0; i<3; i++) { // show the content
for (int j=0; j<3; j++)
std::cout << m[i][j] << "\t";
std::cout << "\n";
}
try { // test the bounds checking.
m[4][1] = 21;
}
catch(std::logic_error &e) {
std::cerr << e.what();
}
return 0;
}
所以,当我们创建了一个矩阵,我们保存它的大小在rows
和cols
。当我们在矩阵上使用operator[]
时,它不会尝试直接返回对矩阵中某个项的引用 - 而是返回一个代理类的实例,用于跟踪行和矩阵,提供和自己的operator[]
。
因此,当您使用matrix[a][b]
时,第一个将a
和matrix
保存到代理对象中。然后在该代理对象上调用[b]
部分。这将检查a
和b
是否在我们为矩阵保存的范围内,如果是,则返回对矢量中正确对象的引用。否则,它会抛出一个std::Logic_error
(可能不是最好的选择 - 只是第一次发生在我身上)。
我应该补充说,这个总体思路有很多变化。仅举一个例子,您可以在编译时指定数组的大小,但将大小作为模板参数传递。这可以有一些优点 - 例如,matrix<int, 2, 3>
和matrix<int, 3, 2>
是完全不同的类型,所以您不能意外地将一个指派给另一个。它也可能有一些缺点(最明显的是,你需要需要来知道编译时的大小,否则根本不会工作)。
您能不能通过您的努力启发我们 – 2013-03-14 05:31:11
当问题是“这意味着什么”时,到目前为止还有什么努力? – FoolishSeth 2013-03-14 05:32:43
作者意味着你返回一个包含嵌入引用的对象,该嵌入引用指向索引行的开始,并且在该对象内的大小限制,以便覆盖'operator []'的边界(对象)可以边界检查索引该维度类似于第一个维度被编入索引。 – WhozCraig 2013-03-14 05:36:33