Search

10.3 — Aggregation

In the previous lesson on composition, you learned that compositions are complex classes that contain other subclasses as member variables. In addition, in a composition, the complex object “owns” all of the subobjects it is composed of. When a composition is destroyed, all of the subobjects are destroyed as well. For example, if you destroy a car, it’s frame, engine, and other parts should be destroyed as well. If you destroy a PC, you would expect it’s RAM and CPU to be destroyed as well.

Aggregration

An aggregation is a specific type of composition where no ownership between the complex object and the subobjects is implied. When an aggregate is destroyed, the subobjects are not destroyed.

For example, consider the math department of a school, which is made up of one or more teachers. Because the department does not own the teachers (they merely work there), the department should be an aggregate. When the department is destroyed, the teachers should still exist independently (they can go get jobs in other departments).

Because aggregations are just a special type of compositions, they are implemented almost identically, and the difference between them is mostly semantic. In a composition, we typically add our subclasses to the composition using either normal variables or pointers where the allocation and deallocation process is handled by the composition class.

In an aggregation, we also add other subclasses to our complex aggregate class 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 aggregate class 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 subclass objects live outside of the scope of the class, when the class is destroyed, the pointer or reference member variable will be destroyed, but the subclass objects themselves will still exist.

Let’s take a look at our Teacher and Department example in more detail.

In this case, pTeacher is created independetly of cDept, and then passed into cDept’s constructor. Note that the department class uses an initialization list to set the value of m_pcTeacher to the pTeacher value we passed in. When cDept is destroyed, the m_pcTeacher pointer destroyed, but pTeacher is not deallocated, so it still exists until it is independently destroyed.

To summarize the differences between composition and aggregation:

Compositions:

  • Typically use normal member variables
  • Can use pointer values if the composition class automatically handles allocation/deallocation
  • Responsible for creation/destruction of subclasses

Aggregations:

  • Typically use pointer variables that point to an object that lives outside the scope of the aggregate class
  • Can use reference values that point to an object that lives outside the scope of the aggregate class
  • Not responsible for creating/destroying subclasses

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 subclasses 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 aggregate, and created/destroyed independently.

It is also possible to create other hybrid aggregate/composition schemes, such as where a class holds independent subobjects like an aggregate, but will destroy them when the class goes out of scope like a composition.

While aggregates can be extremely useful (which we will see more of in the next lesson on container classes), they are also potentially dangerous. As noted several times, aggregates are not responsible for deallocating their subobjects when they are destroyed. Consequently, if there are no other pointers or references to those subobjects when the aggregate is destroyed, those subobjects will cause a memory leak. It is up to the programmer to ensure that this does not happen. This is generally handled by ensuring other pointers or references to those subobjects exist when the aggregate is destroyed.

10.4 -- Container classes
Index
10.2 -- Composition

24 comments to 10.3 — Aggregation

  • 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?

  • Muddasar Azeem

    Hey any one tell me whats error in the EVENT Class?????????????

  • Muddasar Azeem

    #include

    #include

    using namespace std;

    class Time

    { //Time class

    public:

    Time()

    { //default constructor

    hr = 0;

    min = 0;

    }

    Time(int hours, int minutes)

    { //class time constructor that accepts parameters

    if(0 <= hours && hours < 24)//makes sure hours are valid

    hr = hours;

    else

    hr = 0;

    if(0 <= minutes && minutes < 60)//makes sure minutes are valid

    min = minutes;

    else

    min = 0;

    }

    Time setTime(int hours, int minutes)

    { //sets a valid time

    if(0 <= hours && hours < 24)

    hr = hours;

    else

    hr = 0;

    if(0 <= minutes && minutes < 60)

    min = minutes;

    else

    min = 0;

    }

    Time getTime(int& hours, int& minutes)

    {

    //returns the hours and minutes

    hr = hours;

    min = minutes;

    }

    Time printTime()

    {

    //displays the hours and minutes to the screen

    if(hr < 10)

    cout << "0";

    cout << hr << ":";

    if(min < 10)

    cout << "0";

    cout << min < 23)

    hr = 0;

    }

    Time incrementMinutes()

    { //increments minutes by one

    min++;

    if(min > 59)

    {

    min = 0;

    incrementHours();

    }

    }

    private:

    int hr;

    int min;

    };

    class Date

    {//Date class

    public:

    Date()

    {//default constructor

    month = 1;

    day = 1;

    year = 1900;

    }

    Date(int m, int d, int y)

    {//constructor that accepts parameters

    if(m >= 1 && m = 1 && d = 1900 && y = 1 && m = 1 && d = 1900 && y <= 2010)

    year = y;

    else

    year = 1900;

    }

    Date getDate(int& m, int& d, int& y)

    {//returns the month, day and year

    month = m;

    day = d;

    year = y;

    }

    Date printDate()

    {//displays the month, day and year to the screen

    if(month < 10)

    cout << "0";

    cout << month << "/";

    if(day < 10)

    cout << "0";

    cout << day << "/";

    cout << year;

    }

    private:

    int month;

    int day;

    int year;

    };

    class Event

    {//Event class
    private:

    string eventName;

    Time eventTime;

    Date eventDay;

    public:

    Event(int hours = 0, int minutes = 0, int m = 1,

    int d = 1, int y = 1900, string name = "Christmas");

    Event(int hours, int minutes, int m, int d, int y, string name)
    : eventTime(hours, minutes), eventDay(m, d, y)

    {

    eventName = name;

    }

    Event setEventData(int hours, int minutes, int m, int d, int y, string name)

    {

    eventTime.setTime(hours, minutes);

    eventDay.setDate(m, d, y);

    eventName = name;

    }

    Event printEventData()

    {

    cout << eventName << " occurs ";

    eventDay.printDate();

    cout << " at ";

    eventTime.printTime();

    cout << endl;

    }

    };
    int main()

    {//instantiate an object and set data for Christmas

    Event object;

    object.setEventData(6, 0, 12, 25, 2010, "Christmas");

    //print out the data for object

    object.printEventData();

    //instantiate the second object and set date for the fourth of July

    Event object2;

    object2.setEventData(1, 15, 7, 4, 2010, "Fourth of July");

    //print out the data for the second object

    object2.printEventData();
    return 0;
    }

  • 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...???

  • hector

    I love the new look of the site yo :)

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">