#include #include using namespace std; // All definitions are inside the class template. // For an alternative implementation, see array2d-x.cpp. template class Array2D { public: Array2D(unsigned n = 0, unsigned m = 0, int bi = 0, int bj = 0) : data(new T[n * m]), baseRow(bi), baseCol(bj), numRows(n), numCols(m) {} Array2D(const Array2D& a) : data(new T[a.numRows * a.numCols]), baseRow(a.baseRow), baseCol(a.baseCol), numRows(a.numRows), numCols(a.numCols) { for (unsigned i = 0; i < numRows * numCols; ++i) data[i] = a.data[i]; } ~Array2D() { delete[] data; } Array2D& operator=(const Array2D& a) { if (&a != this) { delete[] data; baseRow = a.baseRow; baseCol = a.baseCol; numRows = a.numRows; numCols = a.numCols; data = new T[numRows * numCols]; for (unsigned i = 0; i < numRows * numCols; ++i) data[i] = a.data[i]; } return *this; } T& select(int i, int j) { return data[loc(i, j)]; } const T& select(int i, int j) const { return data[loc(i, j)]; } class Row { public: Row(Array2D& a, int i) : array2D(a), row(i) {} T& operator[](int i) const { return array2D.select(row, i); } private: Array2D& array2D; int row; }; class ConstRow { public: ConstRow(const Array2D& a, int i) : array2D(a), row(i) {} const T& operator[](int i) const { return array2D.select(row, i); } private: const Array2D& array2D; int row; }; Row operator[](int i) { return Row(*this, i); } ConstRow operator[](int i) const { return ConstRow(*this, i); } protected: T* data; int baseRow, baseCol; unsigned numRows, numCols; unsigned loc(int i, int j) const { int di = i - baseRow; int dj = j - baseCol; if (di < 0 || di >= numRows || dj < 0 || dj >= numCols) throw out_of_range("invalid index"); return di * numCols + dj; } }; int main() { // Create a 3x4 array with base indices starting at 1 Array2D a(3, 4, 1, 1); // Fill using operator[][] for (int i = 1; i <= 3; ++i) for (int j = 1; j <= 4; ++j) a[i][j] = (i - 1) * 4 + j; // Print using operator[][] cout << "Array2D contents (3x4, base index 1,1):\n"; for (int i = 1; i <= 3; ++i) { for (int j = 1; j <= 4; ++j) cout << a[i][j] << "\t"; cout << "\n"; } // Copy constructor Array2D b(a); b[1][1] = 999; cout << "\nAfter copy and modifying b[1][1]:\n"; cout << "a[1][1] = " << a[1][1] << " (unchanged)\n"; cout << "b[1][1] = " << b[1][1] << "\n"; // Assignment operator Array2D c(3, 4, 1, 1); c = a; c[2][2] = 777; cout << "\nAfter assignment and modifying c[2][2]:\n"; cout << "a[2][2] = " << a[2][2] << " (unchanged)\n"; cout << "c[2][2] = " << c[2][2] << "\n"; // Zero-based indexing Array2D d(2, 3); // default base indices are 0,0 for (int i = 0; i < 2; ++i) for (int j = 0; j < 3; ++j) d[i][j] = i * 3 + j; cout << "\nArray2D contents (2x3, base index 0,0):\n"; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 3; ++j) cout << d[i][j] << "\t"; cout << "\n"; } }