Aggregation and composition are two sides of the same coin. Both
an aggregate and a composite object encapsulate one or more
sub-objects. But while a composite object owns its sub-objects, an
aggregate object does not. That is, when a composite object is
destroyed, its sub-objects are also destroyed. But with an
aggregate object, the sub-objects are not destroyed.
Aggregate objects typically use references or pointers to refer
to their sub-objects, whereas composite objects typically use
member variables or pointers to refer to their objects. In essence,
a composite object instantiates its own sub-objects, whereas an
aggregate object's sub-objects must be passed to it, typically via
the constructor.
In complex models you will often find a combination of
composition, aggregation and inheritance, even within the same
object.