4 Proxy

Let's set our goal to be able to do the following consumer code:

BArray ba(20);
bool b;

ba[2] = true;
b = ba[3];

This may seem impossible because we cannot return the reference to a single bit position of an integer. However, we can define a proxy class to help us out. A proxy class is a class that is not exposed to the consumer. It is an internal class that is used to ``help with the access of data''.

Let us change our class definition to the following:

class BArray
{
    int *bits;
    unsigned size;
    static const unsigned sizeofint;
    class Lv
    {
        BArray &array;
        unsigned pos;
      public:
        Lv(BArray &who, unsigned pos);
        void setbit(bool v);
        bool getbit(void) const;
    };
  public:
    BArray(unsigned int size);
    BArray(void);
    void setbit(unsigned int pos, bool v);
    bool getbit(unsigned int pos) const;
};

BArray::Lv::Lv(BArray &who, unsigned p):array(who),pos(p)
{
}

void BArray::Lv::setbit(bool v)
{
  array.setbit(pos,v);
}

bool BArray::Lv::getbit(void) const
{
  return array.getbit(pos);
}

Yes, we did define a class Lv inside the definition of BArray. This means BArray::Lv refers to the class Lv that is defined in BArray. Also, observe that the methods of BArray::Lv are just proxies of the methods of the same name in the definition of BArray itself. This ``proxy'' class BArray::Lv may seem somewhat useless at this point.

Next, we add the definition of the assignment operator and cast operators:

operator BArray::Lv::operator bool(void) const
{
  return getbit();
}

bool BArray::Lv::operator = (bool v)
{
  setbit(v);
}

bool BArray::Lv::operator = (const BArray::Lv &v)
{
  setbit((bool)v);
}

This makes it possible to make an BArray::Lv object appear on the left hand side of an assignment operator. It also makes it possible for the compiler to automatically figure how to cast a BArray::Lv object into a boolean value.

The last piece of our puzzle is the creation of a BArray::Lv object. This can be done by the indexing operator of BArray:

BArray::Lv BArray::operator[] (unsigned pos)
{
  return Lv(*this, pos);
}

As an exercise, figure out what is actually happening in the following code:

{
  BArray ba(60);
  bool v1;

  ba[0] = true;
  v1 = ba[1];
  ba[0] = ba[1];
}

Copyright © 2006-09-28 by Tak Auyeung