Composition and Aggregation in C++
Composition and aggregation are both types of relationships in object-oriented design that represent whole-part relationships between objects. They are used to model the way different objects interact with and depend on each other. Though they are similar in concept, they differ in the strength of the relationship between the whole (container) and the part (contained).
Composition is a strong form of aggregation where the contained object cannot exist without the container object. If the container object is destroyed, the contained objects are also destroyed. This is often referred to as a "has-a" or "contains-a" relationship, but it’s more tightly coupled than aggregation.
In composition:
Let's consider a House class that contains Room objects. If a house is destroyed, the rooms in that house are also destroyed because the rooms cannot exist without the house.
#include <iostream>
using namespace std;
class Room {
public:
Room() {
cout << "Room created" << endl;
}
~Room() {
cout << "Room destroyed" << endl;
}
};
class House {
private:
Room room; // House "contains" a Room (composition)
public:
House() {
cout << "House created" << endl;
}
~House() {
cout << "House destroyed" << endl;
}
};
int main() {
House house; // Room will be created when House is created
// When the house is destroyed, the room is destroyed too.
return 0;
}
House object contains a Room object. When the House object is created, the Room is automatically created.House object goes out of scope (in this case, at the end of the main function), the Room object is also destroyed, as it is part of the House.Thus, Composition represents a situation where the part cannot outlive the whole, and the part's lifecycle is dependent on the whole.
Aggregation is a weaker form of association where the contained object can exist independently of the container object. The contained object does not rely on the container object for its existence. While the container object might use or reference the contained objects, the contained objects are not destroyed when the container is destroyed.
In aggregation:
Let's consider a Library class that contains Book objects. If a library is destroyed, the books can still exist because books can be part of multiple libraries, or they can exist independently.
#include <iostream>
#include <vector>
using namespace std;
class Book {
public:
string title;
Book(string t) : title(t) {}
};
class Library {
private:
vector<Book*> books; // Library "has" books (aggregation)
public:
void addBook(Book* book) {
books.push_back(book);
}
void displayBooks() {
for (Book* book : books) {
cout << book->title << endl;
}
}
};
int main() {
Book b1("The Catcher in the Rye");
Book b2("1984");
Library library;
library.addBook(&b1); // Adding books to the library
library.addBook(&b2);
cout << "Books in the library:" << endl;
library.displayBooks(); // Displaying books in the library
// Books still exist independently of the library
return 0;
}
Library class contains a list of Book pointers. The books exist independently of the library. You can see that when a book is added to the library, it is not destroyed when the library is destroyed.Library and Book objects have a loose coupling. The Book objects can be shared by multiple libraries or exist outside the context of the library.Thus, Aggregation represents a situation where the part can exist independently of the whole, and the part’s lifecycle is not tightly bound to the whole’s lifecycle.
| Feature | Composition | Aggregation |
|---|---|---|
| Relationship | Stronger "has-a" or "contains-a" relationship | Weaker "has-a" relationship |
| Lifetime Dependency | The contained object cannot exist without the container | The contained object can exist independently |
| Object Destruction | If the container is destroyed, the contained objects are destroyed | If the container is destroyed, the contained objects are not destroyed |
| Ownership | The container owns the contained objects | The container does not own the contained objects |
| Example | A House contains Rooms |
A Library contains Books |
Composition represents a strong whole-part relationship where the part cannot exist without the whole. The contained objects are tightly bound to the container object, and their lifecycle is managed by the container.
Aggregation represents a weaker whole-part relationship where the part can exist independently of the whole. The container does not manage the lifecycle of the contained objects, and those objects can exist independently or be shared among different containers.
In C++, these concepts help model real-world relationships between objects and are crucial for building flexible and maintainable systems.
Open this section to load past papers