如何重載 [][] 運算符?
一個類 A 有成員 double[][],我希望直接能在對象上進行類似這樣的操作:
A a;
double x = a[0][0];該怎麼實現?
需要一個 helper 類,大約是:
class ARowHelper {
friend class A;
A a_;
size_t r_;
ARowHelper(A a, size_t r) : a_(a), r_(r) {}
public:
double operator[](size_t c) { return a_.data_[r_][c]; }
};
class A {
double** data_;
public:
ARowHelper operator[](size_t r) { return ARowHelper(*this, r); }
};
實際上還要考慮 const-ness 等問題。
operator[]返回一個double*或者不就夠了,使用時[][]裏的第二個[]是指針自帶。
不過存多維數組的話我還是推薦扁平化……
C++怎麼實現效率儘可能高地帶邊界檢查的多維數組模板類??www.zhihu.com與其重載[][]不如重載()。你所需要的操作它都能滿足,而且也不失優雅。
[][]這種表達,很容易聯想到一種數據類型,那就是矩陣:Matrix。
而關於Matrix該如何優雅的重載運算符。isocpp官方恰好有個demo,那就是重載 operator () 而不是[]:
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double operator() (unsigned row, unsigned col); // Subscript operators often come in pairs
double operator() (unsigned row, unsigned col) const; // Subscript operators often come in pairs
// ...
~Matrix(); // Destructor
Matrix(const Matrix m); // Copy constructor
Matrix operator= (const Matrix m); // Assignment operator
// ...
private:
unsigned rows_, cols_;
double* data_;
};
inline
Matrix::Matrix(unsigned rows, unsigned cols)
: rows_ (rows)
, cols_ (cols)
//, data_ ← initialized below after the if...throw statement
{
if (rows == 0 || cols == 0)
throw BadIndex("Matrix constructor has 0 size");
data_ = new double[rows * cols];
}
inline
Matrix::~Matrix()
{
delete[] data_;
}
inline
double Matrix::operator() (unsigned row, unsigned col)
{
if (row &>= rows_ || col &>= cols_)
throw BadIndex("Matrix subscript out of bounds");
return data_[cols_*row + col];
}
inline
double Matrix::operator() (unsigned row, unsigned col) const
{
if (row &>= rows_ || col &>= cols_)
throw BadIndex("const Matrix subscript out of bounds");
return data_[cols_*row + col];
}
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout &
引用自:https://isocpp.org/wiki/faq/operator-overloading#matrix-subscript-op
[][] 的通過中間類還能實現。假如你日後需要[][][]呢?這並不稀奇,比如表示更高維的向量空間。
operator ()比之其他operator的一大好處就是不限制參數個數,並且()看著也並不突兀。
←_← 想好了,支持a[0][0]
就意味著(a[0])[0]
和[](auto r) { return r[0]; }(a[0])
都要有同樣的語義。尤其是後一個,用戶可能會拿r
做各種各樣的操作,作為實現者要想好哪些操作有什麼後果。
如果不想承受這種心智負擔的話,還是不要支持這種寫法為好。a.at(0, 0)
也沒多長。
支持a[0][0]
的方式其他答主都解釋過了,就是讓operator[]
返回一個proxy。
模板大法好,可以套娃套一個任意維度的出來。上星期剛好寫了一個。
用起來像這樣: