Friday, 3 August 2007

Overloading const and non-const member functions

We all know about the function overloading feature in C++. Where we can have the same name given for a function with different signatures. Different signature here means different types or number of arguments for that function.

How about overloading based on constness of a member function?

Consider the scenario below,

class MyArray
{
private:
    int m_iInts[100];  // Array of integers

public:
    int& operator [](int iIndex);  // Overloading subscript operator
};

int& MyArray::operator[](int iIndex) // Definition
{
    return m_iInts[iIndex];
}

We are trying to create an integer array class, with an overloaded operator function for subscript access of the array.

we should be able to say

MyArray objArray;
objArray[10] = 100;

This will establish a call to the member function operator[](int), which returns a reference to the requested array member. It will assign a value to that particular array member.

But, consider the situation below,

void PrintArray(const MyArray &obj)
{
    // Code for printing the elements
    cout<<obj[10]<<endl;
}

Assume that this is a function for printing the array elements. This takes a constant reference to MyArray instance as parameter.

Problem is here!

When we try to print the value by saying obj[10], since the object is of constant type, it will not be able to access the non-const version of operator[](int).

Compiler complains about this saying

no operator defined which takes a left-hand operand of type 'const class MyArray'

In this situation we must declare another version of operator[](int) which will be specifically for const objects.

const int MyArray::operator[](int index) const
{
    return m_iElements[index];
}

This is a const member function - meaning not supposed to change value of any member variable.

Hence we have 2 versions of member functions with same name and even same argument but different in constness.

int& operator [](int iIndex);                 // non-const version
const int operator[](int index) const;    // const version

The first version will be used for all non-const objects and the later will be only used for const objects.

Happy coding!

2 comments:

Anonymous said...

A constant member function can be overloaded with its non-constant equivalent. For overloading purposes, you can think of member functions as if they are ordinary functions with an additional implicit 'this' parameter. When declared as a member of class 'A', method 'void func()' is equivalent to standalone function 'void func(A* this)' and method 'void func() const' is equivalent to standalone function 'void func(const A* this)'. The overloading will work the same way it works for standalone functions. For non-constant object the first version is called, for constant objects the second version is called and there is no ambiguity. Non-const function is preferred when called for a non-const object. For a const object non-const function cannot be called. By using a const_cast we can call a specific variant if the const-ness of the function is not to your satisfaction. However, casting away const and then calling a non-const function for a const object will result in undefined behaviour. C++'s member function declared with a const suffix are called "inspector" (or) "accessor" and without a const suffix are called "mutator" (or) "modifier" since it modifies the state of an object by altering the value of at least one data member.

To cast away constness of a const member function the 'this' pointer should be cast'ed to an ordinary pointer of its class type since inside a const member function the 'this' pointer is actually a const pointer.

Kurian said...

Hello can u give some example programs for overloading '->'operator.It should be helpful for me can you help me..

my e-mail:navaskurian@gmail.com..
help me