I am reviewing some code and a common pattern I am seeing is where a collection of objects is stored as a static member of the class of object being stored.
If, for example, I have a class of objects: class widget, then a list of widgets would be stored as a static std::list within the widget class.
The obvious way to do this would be to have an application level (global level) std::list - and then to find an item lookup this application level list.
I can see that the static member collection idea is more convenient for the user of a. Are there other advantages? Are there other alternatives which should also be considered similar? What are the pros and cons of a and b approach?
Here are the two alternatives in code:
file a.hpp:
//Using collection as static member of class idea
class a {
public:
a();
~a();
class id2a_map;
static class id2a_map id_map;
static a* Find(unsigned id);
unsigned m_id;
};
file a.cpp:
#include <map>
#include "a.hpp"
class a::id2a_map : public std::map<int, a*>
{
};
a::id2a_map a::id_map;
a::a() {
static unsigned id_cnt = 0;
++id_cnt;
id_map.insert(id_map.end(), id2a_map::value_type(m_id = id_cnt, this));
}
a::~a() {
id_map.erase(m_id);
}
a* a::Find(unsigned id) {
id2a_map::iterator i = id_map.find(id);
return i==id_map.end() ? 0 : i->second;
}
file b.hpp:
// b class - not using static collection
class b {
public:
b(unsigned id) : m_id(id) { }
unsigned get_id() const { return m_id; }
private:
unsigned m_id;
};
file main.cpp to exercise a and b:
#include <iostream>
#include <map>
#include "a.hpp"
#include "b.hpp"
int main() {
// approach using static map within class
a obj1;
a obj2;
a obj3;
a obj4;
a* fnd = a::Find(2);
std::cout << "object with id 2 " << (fnd ? "" : "not ") << "found\n";
// application level map
std::map<unsigned, b*> id2b_map;
unsigned id = 0;
b obj5(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj5));
b obj6(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj6));
b obj7(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj7));
b obj8(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj8));
std::map<unsigned, b*>::iterator i = id2b_map.find(2);
std::cout << "object with id 2 " << (i == id2b_map.end() ? "not " : "") << "found\n";
return 0;
}