10.3 — Aggregation

In the previous lesson on Composition, we noted that object composition is the process of creating complex objects from simpler ones. We also talked about one type of object composition, called composition. In a composition relationship, the whole object is responsible for the existence of the part.

In this lesson, we’ll take a look at the other subtype of object composition, called aggregation.


To qualify as an aggregation, a whole object and its parts must have the following relationship:

  • The part (member) is part of the object (class)
  • The part (member) can belong to more than one object (class) at a time
  • The part (member) does not have its existence managed by the object (class)
  • The part (member) does not know about the existence of the object (class)

Like a composition, an aggregation is still a part-whole relationship, where the parts are contained within the whole, and it is a unidirectional relationship. However, unlike a composition, parts can belong to more than one object at a time, and the whole object is not responsible for the existence and lifespan of the parts. When an aggregation is created, the aggregation is not responsible for creating the parts. When an aggregation is destroyed, the aggregation is not responsible for destroying the parts.

For example, consider the relationship between a person and their home address. In this example, for simplicity, we’ll say every person has an address. However, that address can belong to more than one person at a time: for example, to both you and your roommate or significant other. However, that address isn’t managed by the person -- the address probably existed before the person got there, and will exist after the person is gone. Additionally, a person knows what address they live at, but the addresses don’t know what people live there. Therefore, this is an aggregate relationship.

Alternatively, consider a car and an engine. A car engine is part of the car. And although the engine belongs to the car, it can belong to other things as well, like the person who owns the car. The car is not responsible for the creation or destruction of the engine. And while the car knows it has an engine (it has to in order to get anywhere) the engine doesn’t know it’s part of the car.

When it comes to modeling physical objects, the use of the term “destroyed” can be a little dicey. One might argue, “If a meteor fell out of the sky and crushed the car, wouldn’t the car parts all be destroyed too?” Yes, of course. But that’s the fault of the meteor. The important point is that the car is not responsible for destruction of its parts (but an external force might be).

We can say that aggregation models “has-a” relationships (a department has teachers, the car has an engine).

Similar to a composition, the parts of an aggregation can be singular or multiplicative.

Implementing aggregations

Because aggregations are similar to compositions in that they are both part-whole relationships, they are implemented almost identically, and the difference between them is mostly semantic. In a composition, we typically add our parts to the composition using normal member variables (or pointers where the allocation and deallocation process is handled by the composition class).

In an aggregation, we also add parts as member variables. However, these member variables are typically either references or pointers that are used to point at objects that have been created outside the scope of the class. Consequently, an aggregation usually either takes the objects it is going to point to as constructor parameters, or it begins empty and the subobjects are added later via access functions or operators.

Because these parts exist outside of the scope of the class, when the class is destroyed, the pointer or reference member variable will be destroyed (but not deleted). Consequently, the parts themselves will still exist.

Let’s take a look at a Teacher and Department example in more detail. In this example, we’re going to make a couple of simplifications: First, the department will only hold one teacher. Second, the teacher will be unaware of what department they’re part of.

In this case, bob is created independently of department, and then passed into department‘s constructor. When department is destroyed, the m_teacher reference is destroyed, but the teacher itself is not destroyed, so it still exists until it is independently destroyed later in main().

Pick the right relationship for what you’re modeling

Although it might seem a little silly in the above example that the Teacher’s don’t know what Department they’re working for, that may be totally fine in the context of a given program. When you’re determining what kind of relationship to implement, implement the simplest relationship that meets your needs, not the one that seems like it would fit best in a real-life context.

For example, if you’re writing a body shop simulator, you may want to implement a car and engine as an aggregation, so the engine can be removed and put on a shelf somewhere for later. However, if you’re writing a racing simulation, you may want to implement a car and an engine as a composition, since the engine will never exist outside of the car in that context.


Implement the simplest relationship type that meets the needs of your program, not what seems right in real-life.

Summarizing composition and aggregation


  • Typically use normal member variables
  • Can use pointer members if the class handles object allocation/deallocation itself
  • Responsible for creation/destruction of parts


  • Typically use pointer or reference members that point to or reference objects that live outside the scope of the aggregate class
  • Not responsible for creating/destroying parts

It is worth noting that the concepts of composition and aggregation are not mutually exclusive, and can be mixed freely within the same class. It is entirely possible to write a class that is responsible for the creation/destruction of some parts but not others. For example, our Department class could have a name and a Teacher. The name would probably be added to the Department by composition, and would be created and destroyed with the Department. On the other hand, the Teacher would be added to the department by aggregation, and created/destroyed independently.

While aggregations can be extremely useful, they are also potentially more dangerous, because aggregations do not handle deallocation of their parts. Deallocations are left to an external party to do. If the external party no longer has a pointer or reference to the abandoned parts, or if it simply forgets to do the cleanup (assuming the class will handle that), then memory will be leaked.

For this reason, compositions should be favored over aggregations.

A few warnings/errata

For a variety of historical and contextual reasons, unlike a composition, the definition of an aggregation is not precise -- so you may see other reference material define it differently from the way we do. That’s fine, just be aware.

One final note: In the lesson Structs, we defined aggregate data types (such as structs and classes) as data types that group multiple variables together. You may also run across the term aggregate class in your C++ journeys, which is defined as a struct or class that has no provided constructors, destructors, or overloaded assignment, has all public members, and does not use inheritance -- essentially a plain-old-data struct. Despite the similarities in naming, aggregates and aggregation are different and should not be confused.


In the Department/Teacher example above, we used a reference in the Department to store the Teacher. This works fine if there is only one Teacher, but if there is a list of Teachers, say std::vector, we can’t use references anymore.

List elements cannot be references, because references have to be initialized and cannot be reassigned. Instead of references, we could use pointers, but that would open the possibility to store or pass null pointers. In the Department/Teacher example, we don’t want to allow null pointers. To solve this, there’s std::reference_wrapper.

Essentially, std::reference_wrapper is a class that acts like a reference, but also allows assignment and copying, so it’s compatible with lists like std::vector.

The good news is that you don’t really need to understand how it works to use it. All you need to know are three things:
1) std::reference_wrapper lives in the <functional> header.
2) When you create your std::reference_wrapper wrapped object, the object can’t be an anonymous object (since anonymous objects have expression scope would leave the reference dangling).
3) When you want to get your object back out of std::reference_wrapper, you use the get() member function.

Here’s an example using std::reference_wrapper in a std::vector:

To create a vector of const references, we’d have to add const before the std::string like so

If this seems a bit obtuse or obscure at this point (especially the nested types), come back to it later after we’ve covered template classes and you’ll likely find it more understandable.

Quiz time

Question #1

Would you be more likely to implement the following as a composition or an aggregation?
a) A ball that has a color
b) An employer that is employing multiple people
c) The departments in a university
d) Your age
e) A bag of marbles

Show Solution

Question #2

Update the Department/Teacher example so the Department can handle multiple Teachers. The following code should execute:

This should print:

Department: Bob Frank Beth
Bob still exists!
Frank still exists!
Beth still exists!

Show Hint

Show Solution

10.4 -- Association
10.2 -- Composition

180 comments to 10.3 — Aggregation

  • In solution for Question 2. Would not be better to use a foreach loop instead a regular for given that we are using a vector?

    • Alex

      You certainly could. Using a for-each is probably better than using a normal for loop since using a normal for loop introduces the possibility of messing up the array indexing.

  • john

    Hi Alex, I have a question about this example: "A employer containing multiple employees" (also typo here, a -> an). Why should this be an aggregation? If employer is "destroyed", employees are in a way destroyed as well - they still live, but are not employees anymore. Since in this case they exist solely as employees, their existance as a person should not matter to us in the program, their role was an employee and after they loose this status, they might as well be deleted. Is there a mistake in my logic?

    Also, this sentance could use some styling: "In a composition, we typically add our parts to the composition using either normal member variables (or pointers where the allocation and deallocation process is handled by the composition class)."

    • Alex

      Yeah, I get your point. I've updated the quiz question to say, "An employer that is employing multiple people", to make it clear that we should view them as people, not as employees. Does that help?

      Also fixed the typos. Thanks for pointing those out.

      • john

        Yes, this way it's better :)

        Thank you so much for these tutorials, it's incredible that after so many years you're still updating and improving the material.

  • Rohit

    Hi Alex!
    I need to practice more questions for oop c++, can u please provide me some online reference where I can practice for oop just like the above one or tougher. I seriously need them.
    Thank You in advance.

  • Jason Brody

    Hi Alex,
           In the following code

    when dept goes out of scope its default destructor is called.If we defined a destructor manually that deleted the pointer teacher(or any any pointer it takes as its constructor argument) would that be similar to shallow copying?
    i.e. will the destructor delete the dynamic allocated memory?

    Thank you for the awesome tutorials

    • Alex

      Destructors don't have anything to do with copying -- they're just there to (optionally) clean up after a class.

      In the case above, if dept's destructor had deleted teacher, then calling teacher->getName() later would probably crash your program.

  • Michael

    Why do you use the NULL macro in the teacher example when you advised against it in an earlier lesson?

    • Alex

      I forgot to replace the NULL with nullptr when I updated the lesson to be more compliant with best practices. I've fixed it now. Thanks for pointing that out!

  • Ali

    Hi Alex, under the subheading Aggregation, there is a typo. I think you meant to type "To qualify" instead of "To quality".
        Thanks for the great tutorials by the way.

  • Ninja

    Hey Alex, I was reviewing some of the lessons because I had a bit confusion. I recently read a book on design patterns called, "Design Patterns: Elements of Reusable Object-Oriented Software" by a group of authors commonly nicknamed the Gang of Four. The book is from 1995. I was able to understand many of the patterns because of your lessons so I'm very grateful to you.

    Anyways, I'm confused about their use of the word aggregation. I think it means composition but I'm not really sure. Is it the same, do you know? Also, I'm learning UML diagrams and I was wondering if your definitions for composition and aggregation coincide with the symbolic representations for UML (an open diamond with a line connecting objects, etc)? And what I should watch out for in design patterns? I felt like chapter 10 really helped me understand how different design patterns are structured but I'm worried that I might be misinterpreting some of the design pattern structural diagrams in the book.

    • Alex

      One of the annoying things about aggregations in particular is that different people define them differently, so it's likely you'll find other references that do so. I've tried to define them in a way that I believe best aligns with the UML definitions, but there's some wiggle room here.

      > And what I should watch out for in design patterns?

      I'm not sure what you're asking here. Can you clarify?

  • Mauricio Mirabetti

    Since operator<< overload for Department does not need to know the size of m_teacher for anything relevant (like printing the information), I decided to use a for-each. But since declaring const parameters is always a good practice, I noticed all the "chain" of member functions need to present const variations, is that correct? For example, I had to create also a const getName() member to Teacher, besides the non-const one:
    std::string getName() { return m_name; }
    std::string getName() const { return m_name; }
    My operator<< got like this:
    std::ostream& operator<< (std::ostream& out, const Department &d) {
        out << "Department:";
        for (const auto &t :  d.m_teacher)
            out << " " << t.getName();
        out << 'n';
        return out;

    Best regards.
    Mauricio Mirabetti

    • Mauricio Mirabetti

      1. Sorry for the errors on [code][\code] tags;
      2. We could keep just the getName() const version, for that matter, right?

      Thanks again!

    • Alex

      Yep, except if the non-const and const versions of a function are the same, you can just keep the const one (and non-const objects will use it). In your example, you can get rid of the non-const getName() fucntion.

  • James

    Hey Alex, thanks for the great tutorial !,
    one question, why do you dynamically define the teachers:

    rather than just defining them normally and passing as a reference to the required function/class constructor? (i.e. what is the benefit to doing this way)

    • Alex

      Normal members will go out of scope when the function ends, potentially leaving your Teacher/Department with danging pointers if the object they were pointing to went out of scope.

      Defining them dynamically ensures they'll stick around until they're explicitly deleted.

      Because this example is so trivial, it doesn't really matter. But once you get into examples that use multiple functions, it will make a difference.

  • Mila

    Can you clarify the concept of significant other? :))

  • Matt

    In your solution for quiz# 2, inside your friend function, you used "std:cout" instead of "out".

    Also, in the main function of the solution(and in the code before the solution as well), you wrote a comment preceding the creation of the Department object. You wrote:
    "Create a department and use the constructor parameter to pass the teacher to it."
    Yet, the Department class does not have a constructor for this purpose. It uses the member function "add" to add Teacher objects.

  • Matt

    Typo at the beginning. You forgot the "s" at the end of your first sentence.

  • Pranay

    Hello Alex,
    Can we consider aggregation as an substitute of friend function ?

  • Ryan

    In question 2 on the quiz, you say that the "following code should execute"... And on line 16, I find the statement: "dept.remove(t2);". However, the solution omits this statement. Is this a typo? I am having trouble creating a function that can remove a teacher. Thanks!

    • Alex

      I've removed the dept.remove(t2) line from the sample. I was originally going to include the ability to remove teachers as well (seems obvious, doesn't it?) but it turns out that in order to remove something from a std::vector, we need to cover a topic we haven't covered yet (iterators). I'm currently trying to decide whether I should add an introduction to iterators lesson later in this chapter.

  • Nima

    Hello again dear Alex.
    I forget to tell you that have you an article about UMLs too? UMLs for all class relationships in C++ programming?
    Best regards.

    • Alex

      Nope. UML is great for drawing class diagrams, but not strictly related to C++ (more to general programming). It's a great topic though, just not one I intend to cover as part of this tutorial series.

  • Nima

    Sorry dear Alex.
    I'm  wrong.
    Actually it is reflexive association.
    see this:

  • Nima

    Greetings dear Alex.
    Thank you for your great tutorials.
    I search about relationship between classes in C++ and see many of it.
    each site introduce just some part of relationship and I am really confuse.
    I follow your tutorials and see your explanations for composition and aggregation but what about Association, reflective Association, Realization, Generalization, Implementation, Dependency, Multiplicity and many more?
    Can you help me out?
    Best regards.

    • Alex

      I'm just starting to rewrite the lessons for Composition and Aggregation, and am planning on adding a new lesson on Association. I'll undoubtedly add mentions of the other types of relationships as I progress. Generalization is already covered under the chapters on inheritance, and implementation under the chapters on abstract base classes. Dependencies and multiplicities hopefully are obvious.

      What is a reflective association?


    Hi Alex...

    Can you please explain this part of the code:

    Teacher *pTeacher = new Teacher("Bob");

    Especially, Teacher("Bob");

    Can you please link where you discussed it?

    Thanks for great materials ...

    • Alex

      Teacher("Bob") instantiates an object of type Teacher using a constructor that takes a parameter of type const char*.

      It's the class equivalent of something like: int *ptr = new int(5);

      If you're having trouble with this, re-review chapters 6.9 -- Dynamic memory allocation with new and delete, 8.5 -- Constructors, and 8.14 -- Anonymous variables and objects.

  • Kiran C K

    In the above code,  doesn't it cause memory leak if more and more Department objects are created?

    • Alex

      No. Departments don't dynamically create or delete any memory. They can just optionally hold a Teacher object while they exist.

      We would have a memory leak if we didn't delete the Teacher ourselves (in this case, in main()), since Department won't do that for us.

      • Kiran C K

        Got that, Alex. Thanks. What misguided me was the comment in the example :

        cDept went out of scope and in the following line, pTeacher is deallocated. I misunderstood it as even if pTeacher, which is a teacher object is deallocated, it still exists as a cDept object.

        Also, cDept did not allocate any memory for pTeacher, so there is no need for cDept to destroy it, right?

        • Alex

          Right. When cDept goes out of scope, it doesn't destroy the Teacher because it didn't allocate it.

          Since some external party dynamically allocated Teacher, it's up to that external party to delete it.

  • Darin

    Hi Alex,
    I want to ask how do you dereference something like
    Teacher *pTeacher = new Teacher("Bob");
    since I could not fully inderstand the whole aggregration example. The only thing that I was able to understande was that the classes are exchanging the adress that pTeacher holds, but I cannot actually do anything with it(since I cannot dereference it). If possible could you please explain?

  • maxatan

    Hi ! and congratulations for your job !

    However, I have a question : What would be the code with more than one teacher belonging to the Department ? How will you implement it ? With a list of pointers to Teachers (list) ?

    Thank you in advance for your advice

  • mccp13

    I still don't get the pointer *m_pcTeacher. when m_pcTeacher recieves pTeacher, it means that m_pTeacher and pTeacher are pointing to the same address. So when m_pcTeacher is destroyed doesn't that mean that the address to which it is pointing to is freed, so when pTeacher gets the contents of the address, it could have changed since it is already free and ready to be used by some other program...???

    • Alex

      When dept is destroyed, the m_teacher member pointer is destroyed, but it is not deleted (that is, the contents that it was pointing to are still valid)

  • hector

    I love the new look of the site yo :)

  • Amit

    Thanks for teh description but there are couple of loose ends:
    1. How is association different from aggregation and composition ? You may want to add a section on that
    2. If a class has a data member(only one) which points to another object but this is not allocated/dealloacted in constructor and destructor. Will this be aggregation or composition ? For teh relation to be aggregation is it necessary that you should have more that one object of the same type ?

  • auasp

    the heading of this lesson is Aggregration.
    (one extra r)

  • serenity

    f117f117f117677: "class Department" doesn't actaully delete the teacher; the only thing removed when it's destroyed is its pointer to the teacher. The pointer in main() remains and is still valid, so there is no wild pointer and no double delete.

  • f117f117f117677

    Hi: Alex
    as you said
    there are two pointers point to Teacher("Bob"). pTeacher and m_pcTeacher

    if aggregate class is destroyed then m_pcTeacher is destroyed. So
    teacher("Bob") is gone(died).

    but delete pTeacher again? is this problem? pTeacher become a wild pointer?

  • shouldn't

    return 0?

    • Arnav Srivastava

      If you don't write "return 0" compiler won't complain as nowadays every compiler takes care of this by considering "0" as a default return value from "int main"

  • Prateek Jain

    How do you handle the situation when subclass object gets destroyed? In our case, if the teacher dies for some reason (say heart attack:-) in case of real world situation), the pTeacher pointer will still have some value but that value will no longer be valid. If Department class has some member which access pTeacher, this could give rise to some potential problem.
    If you somehow can pass a message to Department class, it can make pTeacher equal to NULL but checking (pTeacher == NULL) everywhere in Department class doesn't seem to be a good idea.
    How do you incorporate it into your design?

    • Alex

      Great question. In real life, if a teacher died, someone would need to notify the department so they could remove the teacher from the roster.

      In C++-land, it's better to do things the other way around: Before you kill an object, make sure that all pointers or references to it are removed, and then kill it (killing something should always be the last step). In terms of aggregations, this likely means writing a function to set the appropriate child to null. In cases where the aggregate has a single instance of the object and you know what it is, you can just use an access function to set the value to null (e.g. setTeacher(nullptr)).

      In a more complex aggregation (e.g. a Department that can hold multiple Teachers), you'll probably need to write a remove() function and pass in the specific Teacher to remove as an argument so it knows which of the multiple teachers you want to remove.

      You should check if teacher == nullptr everywhere inside your Department, because this is a valid state for Department.

  • Stuart

    Alex, I don't understand why the pointer pcTeacher is assigned NULL as a Department constructor parameter, because it assigns to the address of the pTeacher pointer when an object of Department is instantiated. It seems like it's never a null pointer. (?)

    • It's assigned NULL as a default parameter just in case the programmer wants to create a department with no teacher. For example:

      In this case cDept would call the Department constructor with pcTeacher set to NULL. This NULL value would then be assigned to cDept.m_pcTeacher by the constructor.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]