Tuesday, January 29, 2008

C++ overloading operator& ( Or Find the addess of a object)

Recently a friend of mine ( name : rejeesh ) asked me "how to find the address of an object if the & operator is  overloaded" ?

Example class is like this

class AddressBlocker
{

public:

  AddressBlocker*
  operator &()  {  return 0;  }
};


so if you try to execute a code like this

AddressBlocker op;
AddressBlocker* Pt = &op;

Pt will be NULL. Pt =  &op will not pass the  real address of op to Pt. Because the operator is overloaded.

So how to get the address ??

When he asked me it, i found two solutions with templates .  One deriving a new class from the required class , and the second one is
more tricky. I will explain ( by showing the code) here both two methods.

Method 1.

template<typename T>
class Addressfinder : public T
{
public:
    Addressfinder* operator&() { return this; }
};

and you use it like this
AddressBlocker
blockMe;

Addressfinder<AddressBlocker>& finder = static_cast<Addressfinder<AddressBlocker>&> ( blockMe );


and address can be retrieved by simple  "AddressBlocker* pValid = &finder;" . This will work since i overloaded the &operator in Addressfinder class.
Method 2.

I think this is more good compared to the above. Since it is not creating any more relationships with the classes. and also no need for casting to use it.

template <typename T>
class AddressfinderII
{
    T& tOb;
public:
    AddressfinderII(T& t): tOb(t){}
    T * operator&()
    {
        return reinterpret_cast<T*> ( *reinterpret_cast<int *>( this ) );
    }
};

usage is like this

AddressBlocker blocker;
AddressfinderII<AddressBlocker> finderII(blocker);AddressBlocker * pAddress = &finderII;

if you look the size of this class , it just 4 bytes. because storing reference is same as pointer.
The class object's memory will have just the real address of object. And i extracted that value in operator& and returned.

Ok.. There is a more convenient way , he told me . and it is used in boost libraries. anyway i could find some alternatives 

Method 3

template<typename T>
T* addessof(T& t)
{
    return reinterpret_cast<T*>(& reinterpret_cast<int&> ( t ) );
}

and can be use like addressof( blocker); it is more convenient. it has similarities with method 1. So now no more address hiding..