Showing posts with label Overloading. Show all posts
Showing posts with label Overloading. Show all posts

Tuesday, 4 September 2007

Global vs Member overloaded operator new

In an earlier post we saw how to overload operator new, which will allow us to have customized memory allocation for an object on heap.

Its possible to place this overloaded operator new function either globally or as member function within a class.

 

// Global overloaded operator new
void *operator new(size_t size)
{
    return malloc(size);
}

 

// Class CTest
class CTest
{
public:

    // Member overloaded operator new
    void *operator new(size_t size)
    {
        return malloc(size);
    }

};

 

Is there any behavioral difference between these two versions of operator new?

Yes, there is.

If we have overloaded new as a member function within a class, it will always have high precedence over the globally defined version.

If we have a globally defined operator new function, the same will be used for all classes which doesn't have overloaded operator new defined within.

If both exist, the member version will be preferred over the global version.

Is there any advantage of this feature?

Yes.

Global version of overloaded operator new will be very much useful when we need to have a common strategy for memory allocation for all the classes in the module.

If we are in a situation where we need to have a specific way for allocation for a particular class which is different from others then we can overload operator new for the class with desired allocation method. A good example would be to allocate and initialize the allocated memory with zeros.

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!