Skip to main content

Section 18.11 Implementing Aggregation

Subsection 18.11.1 Variable Ownership Semantics

To implement aggregation in C++, we need to have a variable that gives us access to some memory without owning it. That means we can’t use a regular variable, like a Point m_center, as regular variables β€œown” a chunk of memory. When a regular variable goes out of scope, the variable it names goes away. Pointers (and references) are different. A pointer just names a place in memory where we store a memory address (hopefully the address of some useful piece of data). When the pointer goes away, all that is lost is that copy of the address. The data at that address is not lost.

Insight 18.11.1.

Different types of variables have different ownership semantics (meaning).
  • A β€œregular” variable (like x in int x = 10;) owns the memory it is using.
  • A β€œreference” variable (like r in int& r = x;) does NOT own the memory it is using. It is an alias for another variable.
  • A β€œpointer” variable (like p in int* p = &x;) may or may not own the memory it points at. Until we learn about dynamic allocation, we will assume pointers do NOT own the memory they point at.
So to implement aggregation, we need to use pointers or references. There are some limitation that come with references: you can’t have a null reference and you have to initialize references when they are created. So if we chose reference variables, we could not have a Person with no spouse (a null value for a spouse). And we would have to use the initialization list to make sure that the spouse was initialized as the space for it was allocated. To avoid these limitations and keep things consistent even in situations where they might not matter, we will always use pointers to implement aggregation.

Note 18.11.2.

We also could implement composition using pointers if we made sure that each container object pointed to a unique object and that those contained objects went away when their container did. We will avoid that complication.

Subsection 18.11.2 Aggregation Using Pointers

A Circle class built using aggregation will be very similar to the composition version, but will store a pointer to a Point instead of a Point. A simplified version of this new Circle class might look like:
Listing 18.11.1.
Key things to note about this implementation:
  • The m_center is now a Point* (line 24).
  • The constructor takes a Point * (line 5).
  • To use m_center’s functions, we need to use the -> operator (lines 14, 18).
  • When we construct a Circle, we pass it the address of an already existing Point (lines 34 and 37).
We have to pass an existing Point object to the Circle constructor because the Circle will not have its own storage for a Point. Instead, it will just store the address of a Point, which means that Point must already exist elsewhere in memory.
A memory diagram for the main function after all of the Circles are constructed would look lime the image below. c1 and c2 don’t hold their own Point objects, they hold the memory address of p1.
In Circles c1 and c2, the m_center holds the memory address of Point p1
Figure 18.11.2. Memory diagram of p1, c1, and c2 using aggregation.
This means, that any change to p1 will be β€œseen” by the two Circle objects. We can see this in the last few lines of the program above. Shifting Point p1 affects the center of both c1 and c2 because they both use the actual Point p1 as their center.

Note 18.11.3.

This is a critical distinction between aggregation and composition. If we made two circles from a Point p1 with the composition version of Circle, each Circle would make its own copy of the data from p1 and store that data.
In Circles c1 and c2, the m_center hold copies of the data from p1
Figure 18.11.3. Memory diagram of p1, c1, and c2 using composition.
Given this structure in memory, future changes to p1 would not affect either Circle’s center point as those are different objects in memory.

Checkpoint 18.11.1.

Checkpoint 18.11.2.

If we modeled aggregation between a Person and their best friend (also a Person) with references instead of pointers, what is something we could not do?
  • We could not have a Person with no set best friend.
  • We could not change the best friend of a Person.
  • We could not have two People share the same spouse.
You have attempted of activities on this page.