Paul Brettschneider a écrit :
[...]
Generally speaking: if an object has an explicit lifetime, it
almost always also has identity, and so won't support copy, and
can't be put in a standard container. And the standard
containers don't support polymorphism either. There are cases
where it might be appropriate to have a container own an object,
i.e. by containing it via some sort of smart pointer, but they
are fairly rare. Most of the time, the container is at the
service of some higher level concept, and it is the
implementation of the higher level concept (often the object
itself) which takes charge of managing object lifetime.
Here the new() is hidden in operator[] of std::map. IMHO new
and delete are low-level functions (or call them operators)
and application developers should not have to care too much
about them. But maybe I'm just silly?
Maybe. In the applications I work on, or have worked on (large
scale servers, mostly, but also one GUI framework), the
You obviously work on much more complex applications than I
do, but what you describe in response to Ian "feels" like a
layering violation to me. Why should an object know about its
containers?
Because part of the object's semantics are that it can be
"found" by some external identifier. Ideally, you're right, of
course, and one could imagine using some variant of the observer
pattern, but for application level objects, I think it's usually
overkill. The object is designed to work at part of the
application, and the fact that the application uses some
specific object map is part of that application. Most of the
time, it will in fact be "partially" hidden, in the sense that
the object simply enrols and deenrols with some sort of
"dictionary", but that's really only partial hiding.
I think it just shows that I come from a RDBMS background and
typically I collect all my objects in containers akin to
boost::multi_index_container. So while you create objects
which add themselves to containers, I ask the container to
give me an object of my liking.
I bet your approach is more idiomatic OO/C++, but my code
hasn't to be read by other C++ experts, so it's no problem.
Well, it's more idiomatic in the places I've worked in, but I
think you have a valid point when you say that having the object
know about the lookup service breaks encapsulation to some
degree. Or course, a lot of objects have to know about it
anyway, since they will use it as a client, and not just for
enrolling themselves. But I think the main reason that it's
widely used is that the breach of encapsulation has never been
felt to be enough of a problem for someone to look for a good
solution.
Sure. But you can deal with it by either calling new or delete
or by telling a container to add/delete objects.
Sure. But that's sort of my point. If the application wants to
delete an object, the most obvious way is "delete object";
something like "objectMap.erase( object->id() )" seems a bit
more indirect, and makes it less obvious what is actually
happening.