A Developer's Diary

Jan 31, 2011

Overloading operator()

Browsing through some of the open source code implementation in C++, came across the function void operator()()
Q. Why would one use operator() in the first place?
A. Simplicity of usage. Of course, less intuitive if you are seeing it's use for the very first time.

The program below implements a matrix and uses operator() as a replacement of subscript operator[] to retrieve and set values at the particular location.

#include <iostream>

//File: Matrix.h

class Matrix
{
public:
    Matrix(size_t rows, size_t cols);
    Matrix(const Matrix &m);
    virtual ~Matrix();

    Matrix& operator=(const Matrix &m);
    double& operator()(size_t row, size_t col);
    //double operator()(size_t row, size_t col) const;

    size_t getRows() const;
    size_t getCols() const;

private:
    Matrix();
    void copy(const Matrix &m);
    void init(double value);

    size_t _nrows, _ncols, _size;
    double *_data;
};

Excercise
Why is the method commented out in the above code?
//double operator()(size_t row, size_t col) const;

#include "Matrix.h"
#include <iostream>
#include <iomanip>

//File: MatrixTest.cpp

void read_matrix(Matrix &m)
{
    for(size_t i = 0; i < m.getRows() ; ++i)
    {
        for(size_t j = 0; j < m.getCols() ; ++j)
        {
            m(i, j) = (i * m.getCols()) + j;
        }
    }
}

void print_matrix(Matrix &m)
{
    std::cout << std::setiosflags(std::ios::left);
    for(size_t i = 0; i < m.getRows() ; ++i)
    {
        for(size_t j = 0; j < m.getCols() ; ++j)
        {
            std::cout << std::setw(6) << m(i, j);
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

int main()
{
    //First Matrix
    Matrix m(4, 5);
    read_matrix(m);
    print_matrix(m);

    //Second Matrix
    Matrix n(5, 4);
    read_matrix(n);
    print_matrix(n);

    //Assignment Operator Test
    n = m;
    read_matrix(n);
    print_matrix(n);

    //Copy Constructor Test
    Matrix o(n);
    read_matrix(o);
    print_matrix(o);
}

Output:

The Matrix implementation class
#include "Matrix.h"

using namespace std;

Matrix::Matrix(size_t rows, size_t cols) :
_nrows(rows), _ncols(cols), _size(rows * cols)
{
    _data = new double[_size];
    init(0.0);
}

Matrix::~Matrix()
{
    delete[] _data;
    _data = NULL;
}

Matrix::Matrix(const Matrix &m)
{
    copy(m);
}

Matrix& Matrix::operator=(const Matrix &m)
{
    if(this == &m)
    {
        //do nothing
    }
    else
    {
        delete[] _data;
        copy(m);
    }
    return *this;
}

double& Matrix::operator()(size_t row, size_t col)
{
    size_t idx = row * getCols() + col;
    return _data[idx];
}

/*
double Matrix::operator()(size_t row, size_t col) const
{
size_t idx = row * getCols() + col;
return _data[idx];   
}
*/

size_t Matrix::getRows() const
{
    return _nrows;
}

size_t Matrix::getCols() const
{
    return _ncols;
}

void Matrix::init(double value)
{
    for(size_t i = 0; i < _size; ++i)
    {
        _data[i] = value;
    }
}

inline void Matrix::copy(const Matrix &m)
{
    _nrows = m._nrows;
    _ncols = m._ncols;
    _size = m._size;
    _data = new double[_size];
    for(size_t i = 0; i < _size; ++i)
    {
        _data[i] = m._data[i];
    }
}

References:
www.parashift.com

No comments :

Post a Comment