6.9.  Managed Containers, Composites and Aggregates

[ fromfile: inheritance-intro.xml id: managedcontainers ]

Qt's value containers are containers of uniform (same-typed) values - e.g. QString, byte, int, float, etc. Pointer containers are containers of pointers to (polymorphic commonly-typed) objects. They can be managed or unmanaged.

Both kinds of containers can grow at runtime by allocating additional heap memory as needed. This is always done in an exception-safe way, so you don't need to worry about possible memory leaks.

In the case of pointer containers to heap objects, however, one must decide which class is responsible for managing the heap objects. UML diagrams can distinguish between managed and unmanaged containers by using composite (filled diamond) and aggregate (empty diamond) connectors, as shown in Figure 6.6.

Figure 6.6.  Aggregates and Compositions

Aggregates and Compositions

In general, a managed container is a composite, because the container manages its pointed-to objects. In other words, when a composite is destroyed, it destroys (cleans up) its entire self because the smaller objects are part of its composition.

When one object embeds another as a subobject, it is also considered a composition.

In Figure 6.6, there are two kinds of Customer containers: CustomerList and CustDb. CustDb and CustomerList both reuse template containers. CustomerList objects are aggregates – temporary structures to hold the results of a query, or a user selection. CustDb, on the other hand, is a singleton composite that manages all the Customer objects that exist.

In the case of the Customer and Address relationship, this diagram indicates that one or more Address objects should be associated with a particular Customer. When the Customer object is destroyed, it is reasonable to destroy all its Address objects at the same time. Thus, the Customer object manages its Addresses, which gives you another example of a composite relationship.

[Note] Note

This suggested design does impose some limitations on possible use of Address – in particular, there is no easy way to find all Customers at a particular Address. If Address and Customer were independently managed, then you could form bidirectional relationships between the classes.

Typically, a managed container deletes any heap objects it "owns" when the container itself is destroyed. With a Qt container of pointers, you can use qDeleteAll(container), an algorithm that calls delete on each element in the container.

Copying a managed container can be defined in a number of ways:

An aggregate container is a container that provides only an indexing or reference navigation mechanism to its contents.

In this case, the container does not manage its objects – it only provides a convenient way to access them. When an aggregate container is copied, only references to the collected objects are copied. When an aggregate container is deleted, only the references are removed. There is no impact on the underlying objects in the container.

[Note] Note

A managed container is a composition, and an unmanaged container of objects is usually (but not always) represented in a UML diagram as aggregation.