Thread: encapsulation and accessing large maps?

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    4

    Question encapsulation and accessing large maps?

    Suppose that I have an object that has a very large map. Consider now, another object that wishes to iterate through every item in the map owned by the first object. Lets name these two objects, ObjMap and ObjNoMap. It is tempting to write a ObjMap::getMap function that returns a pointer to the internal map object. However, this breaks encapsulation. Another option is to return the whole map by value, but then there is a very large hit in efficiency. Still another option would be to return a const_iterator. Consider this last option. If I return a const_iterator to the map from ObjMap am I still breaking encapsulation? On the one hand ObjNoMap will gain read access to an internal member of ObjMap, but at least ObjNoMap cannot mutate the internal member of ObjMap. Is there a viable solution that will allow me to keep with the object oriented methodology of encapsulation without taking a majore hit in efficiency?

    Thank you for your time.

    dustfinger.

  2. #2
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    If only a number of private classes wish to access the map, you could implement them as friends of the map. But if you want to provide access (that is, only access) to the map to the public, I think a const_iterator is the way to go.

    Note that encapsulation isn't about locking up everything in a neutronium-alloy-whatsit safe and making sure no one gets into it. It's about allowing folks to get only what they need from an object, and nothing else.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I think returning the iterator is perfectly acceptable. You could typedef it to a different name (or maybe just ObjMap::iterator) so that if you ever do need to change the implementation of ObjMap to not use the same kind of map, you can just change the typedef. As long as the new implementation can provide something with the same interface as the original map const_iterator, the calling code in ObjNoMap will not need to be updated.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    4
    One problem with returning a const_iterator is that I will not know when I am at the end of the map. I could write a function that takes a reference to a const_iterator, which will be set to the end of the map, and returns a const_iterator, which will be set to the start of the map.
    Code:
    ObjMap::const_iterator endItr;
    ObjMap::const_iterator itr = getMap(endItr);
    However, what if I want to iterate through the map more than once for some reason. Then I could do something like.
    Code:
    ObjMap::const_iterator startItr;
    ObjMap::const_iterator endItr;
    ObjMap::const_iterator itr;
    getMap(startItr, endItr);
    for(itr=startItr; itr!=endItr; ++itr)... you get the point
    But that seems messy. Is there a cleaner way to deal with this problem. I feel compelled to only want to return a const_iterator, but then I want to be able to iterate to the very end of the map, and so I need to know when I am at the end.

    dustfinger.

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > One problem with returning a const_iterator is that I will not know when I am at the end of the map.

    Not sure if I follow you on this one...

    objMap.end() will let you know if you have hit the end of the map.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    4
    Oops. I did not mean to write getMap is a member of ObjMap. This is what I really meant:

    The code in question is being called from ObjNoMap. I want read only access to a very large map that ObjMap contains. So I write:
    Code:
    AMap::const_iterator ObjMap::getMap();
    and call getMap from ObjNoMap. The problem is that I recieve a const_iterator to the begining of the map, but do not know where the end is. So there are two solutions that I can think of. Return a const pointer to the map itself, or have getMap take two reference parameters of type AMap::const_iterator and set them appropriately. What is the best solution here?

    Note: the code in my previous post should have looked more like:
    Code:
    AMap::const_iterator startItr;
    AMap::const_iterator endItr;
    AMap::const_iterator itr;
    getMap(startItr, endItr);
    for(itr=startItr; itr!=endItr; ++itr)... you get the point
    dustfinger.

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >What is the best solution here?
    Why not just add begin and end member functions to AMap? It sounds like you're writing a wrapper container with a map as the internal container, so there shouldn't be any problem with matching a subset of the map interface.
    My best code is written with the delete key.

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    4
    Why not indeed. I cannot believe that I never thought of that. I will sheepishly go back to what I had been doing before I interupted this forum. Augh!!!!

    dustfinger.

Popular pages Recent additions subscribe to a feed