19.9.3. The Function Call operator()

[ fromfile: useroperators.xml id: fncalloperator ]

The function call operator, operator() is overloadable as a nonstatic member function. It is frequently used to provide a callable interface, an iterator, or a multiple index subscript operator. It is more flexible than operator[] because it can be overloaded with respect to different signatures. In Example 19.16, there is a multiple-subscript operator for a Matrix class.

Example 19.16. src/operators/matrix/matrix.h

[ . . . . ]
class Matrix {
public:
    Matrix(int rows, int cols);                 1
    Matrix(const Matrix& mat);                  2
    ~Matrix();
    double& operator()(int i, int j);
    double operator()(int i, int j) const;
    // Some useful Matrix operations
    Matrix& operator=(const Matrix& mat);       3
    Matrix operator+(const Matrix& mat) const;  4
    Matrix operator*(const Matrix& mat) const;  5
    bool operator==(const Matrix& mat) const;
    int getRows() const;
    int getCols() const;
    QString toString() const;
private:
    int m_Rows, m_Cols;
    double  **m_NumArray;
    //Some refactoring utility functions
    void sweepClean();                          6
    void clone(const Matrix& mat);              7
    double rcprod(int row, const Matrix& mat, int col) const; 
                                                /* Computes dot product of the host's row with  mat's col. */
};
[ . . . . ]

1

Allocates and zeros all cells.

2

Copy constructor - clones mat.

3

Deletes host content, clones mat.

4

Matrix addition.

5

Matrix multiplication.

6

Deletes all cells in the host.

7

Makes a copy of the host using new memory.

<include src="src/operators/matrix/matrix.h" href="src/operators/matrix/matrix.h" id="matrixh" mode="cpp"/>


Example 19.17 implements the two versions of the multiple-subscript operator that are needed – one for getting and one for setting values from the Matrix. Notice that this implementation makes use of the (unprotected) array subscripting that is the native equipment of C/C++ arrays. This cautious code for proper handling of the underlying array helps to produce a safe and reliable public interface that uses (range-checking) function-call subscripting for the Matrix class.

Example 19.17. src/operators/matrix/matrix.cpp

[ . . . . ]

double Matrix::operator()(int r, int c) const {
   assert (r >= 0 && r < m_Rows && c >= 0 && c < m_Cols);
   return m_NumArray[r][c];   
}

double& Matrix::operator()(int r, int c) {
   assert (r >= 0 && r < m_Rows && c >= 0 && c < m_Cols);
   return m_NumArray[r][c];
}

<include src="src/operators/matrix/matrix.cpp" mode="cpp" href="src/operators/matrix/matrix.cpp" id="matrixsub" segid="sub"/>


Example 19.18 shows the implementation of the constructor, which needs to know how many rows and how many columns are wanted for this Matrix.

Example 19.18. src/operators/matrix/matrix.cpp

[ . . . . ]

Matrix:: Matrix(int rows, int cols):m_Rows(rows), m_Cols(cols) {
    m_NumArray = new double*[rows];
    for (int r = 0; r < rows; ++r) {
        m_NumArray[r]  = new double[cols];
        for(int c = 0; c < cols; ++c)
           m_NumArray[r][c]  = 0;
    }
}

<include src="src/operators/matrix/matrix.cpp" mode="cpp" href="src/operators/matrix/matrix.cpp" id="matrixctor" segid="ctor"/>


The constructor allocates space for double values in each of the cells of the Matrix, so the destructor, implemented in Example 19.19, must delete each of those cells. We factored out the deletion code in case it is needed to implement other member functions.

Example 19.19. src/operators/matrix/matrix.cpp

[ . . . . ]

void Matrix::sweepClean() {
   for (int r = 0; r < m_Rows; ++r)
      delete[] m_NumArray[r] ;
   delete[] m_NumArray;
}

Matrix::~Matrix() {
   sweepClean();
}

<include src="src/operators/matrix/matrix.cpp" mode="cpp" href="src/operators/matrix/matrix.cpp" id="matrixdtor" segid="dtor"/>