Link to home
Start Free TrialLog in
Avatar of bs161900
bs161900

asked on

Getting pointer to an object stored in a map

Hi,

I have a template based map that is declared as follows :
class CMyMap : public CMap<CString, LPCTSTR, CMyObject, CMyObject&)
{
public:
      CMyMap() {};
      ~CMyMap() {};

protected:
      CMyObject *GetValuePtrFromPos(POSITION pos);
}

I stored some items in it.

Now I want to iterate through the map and get a pointer to each object
stored. The pointer has to point to the object embedded in the CAssoc
structure maintained by the map, so that it stays valid until the map´s
elements are removed.

CMyMap map;
POSITION pos=map.GetStartPosition();
while (pos != NULL)
{
   CString strKey;
   CMyObject Obj;

   CMyObject* pObj = map.GetValuePtrFromPos(pos);
   map.GetNextAssoc(pos, strKey, Obj);
   :
}

Could somebody give me some hints of how to implement GetValuePtrFromPos
and tell me what the relation is between a POSITION type variable and an
internal CAssoc structure. Every help would be very appreciated.

Thanx in advance.
ASKER CERTIFIED SOLUTION
Avatar of abk102299
abk102299

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of abk102299
abk102299

I am sorry - a bug. For pointers collection should be:CMap<CString, LPCTSTR, CmyObject*, CmyObject*>
( remove the "const" modificatior )
Avatar of bs161900

ASKER

First of all I want to apologize for my late respons and
secondly I want to thank you for your effort in trying to
help me.

You are right saying that using a pointer collection would
be far more easy to solve my problem.
When I first began writing my application, I used object
pointers instead of objects, but I encountered some problems
when I had to compare the contents of those objects. (Using
pointers requires that you overwrite the global template function
CompareElements). Now that I am a little more familiar with the
template collections, I am considering using pointers again.

Still my question remains. Suppose I am storing bare objects
in a CMap derived collection class.
Internally, they are embedded in a CAssoc structure the framework
dynamically created. So they have an address.
I tried to implement GetValuePtrFromPos this way :

CMyObject* CMyMap::GetValuePtrFromPos(POSITION pos)
{
   return &(((CAssoc *) pos)->value);
}

But this did not work. Why ??
As for your GetValuePtrFromPos I think the following implementation would work:

CMyObject* CMyMap::GetValuePtrFromPos(POSITION pos)
{
      CAssoc* pAssocRet = (CAssoc*)pos;
      ASSERT(pAssocRet != NULL);
      if (pAssocRet == (CAssoc*) BEFORE_START_POSITION)
      {
            // find the first association
            for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
                  if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
                        break;
            ASSERT(pAssocRet != NULL);  // must find something
      }
      return &(pAssocRet->value);
}

BUT the BEFORE_START_POSITION constant here just corresponds to the FIRST value that may be different with time. Other positions just represent some addresses which also may be filled with different CMyObject objects re-associated with the KEY. In addition there are several CMap's internal implementation details used here and they may be ( not likely ) changed in later MFC versions.

As for me the pointers approach just looks more transparent.
Your routine seems to work fine. It gives me a better insight in the
workings of a map.
Although I changed my map implementation so that it holds object pointers
now, and all works fine as well. Thanks for your help.