Aggregation in C++

OOP (Object-Oriented Programming) aggregation is a relationship between two classes where one class contains an instance of another class as a member. It represents a "has-a" relationship, where one class has a composition of another class.

In aggregation, the contained class (referred to as the "part" class) can exist independently, and it can be shared by multiple instances of the containing class (referred to as the "whole" class). The lifespan of the part object is not controlled by the whole object. In other words, if the whole object is destroyed, the part object can still exist.

Aggregation is often represented by a member variable of one class being an object of another class. The whole class can access the members of the part class and use its functionality.

In summary, OOP aggregation represents a "has-a" relationship between classes, where one class contains an instance of another class as a member. It provides a way to represent complex relationships and build more flexible and reusable code structures.


Code Example

Address header file

// Address.hpp // Aggregation Example // Created by Kevin Roark on 6/16/23. #ifndef Address_hpp #define Address_hpp #include <string> using namespace std; class Address { private: //class attributes / properties string street; string city; string state; string zip; public: // Getter methods string getStreet() const; string getCity() const; string getState() const; string getZip() const; // Setter methods void setStreet(string newStreet); void setCity(string newCity); void setState(string newState); void setZip(string newZip); //Class Methods string print() const; //constructor Address(string street, string city, string state, string zip); Address(); // default constructor Address(const Address& source); // Copy constructor }; #endif /* Address_hpp */

This is a C++ header file for the Address class. The class has private member variables (or properties) - street, city, state, and zip.

This class is a typical example of a Plain Old Data (POD) structure where the member variables are private and are accessed through public getter and setter methods. Getter methods return the value of the member variables, and setter methods modify the value of the member variables.

The class also provides a print method to output the address information.

The Address class provides three constructors:

  • A parameterized constructor that takes four strings (street, city, state, zip). This constructor is used when you want to create an instance of the Address class and you have all the information at hand.

  • A default constructor that takes no arguments. This constructor will be used when you want to create an instance of the Address class but you do not have any information at hand at the time of creation.

  • A copy constructor that takes a reference to another Address object. The copy constructor is a special constructor used for creating a new object as a copy of an existing object. The copy constructor is needed when you want to make a copy of an object to prevent modifications to the original object, for example.

The #ifndef, #define, and #endif preprocessor directives are used to prevent double inclusion of the header file. When the preprocessor sees the #include "Address.hpp" directive, it checks if Address_hpp has been defined. If not, it defines it and includes the contents of the header file. If it has already been defined, it skips the contents. This can be helpful in larger programs where multiple files might include the Address.hpp header file.

Code File for Address

// Address.cpp // Aggregation Example // Created by Kevin Roark on 6/16/23. #include <string> #include <iostream> #include "Address.hpp" //Getter methods string Address::getStreet() const { return street; } string Address::getCity() const { return city; } string Address::getState() const { return state; } string Address::getZip() const { return zip; } //Setter Methods void Address::setStreet(string street) { this->street = street; } void Address::setCity(string newCity) { city = newCity; } void Address::setState(string newState) { state = newState; } void Address::setZip(string newZip) { zip = newZip; } //Class Methods string Address::print() const { string myReturn = ""; myReturn += this->getStreet() + "\n" + this->getCity() + ", "; myReturn += getState() + "\n" + getZip(); return myReturn; } //constructors Address::Address(string street, string city, string state, string zip) { this->street = street; this->city = city; this->state = state; this->zip = zip; } Address::Address() { street = "NA"; city = "NA"; state = "NA"; zip = "NA"; } // Copy constructor Address::Address(const Address& source) { this->street = source.street; this->city = source.city; this->state = source.state; this->zip = source.zip; }

This is the implementation file for the Address class, where each method declared in the header file ("Address.hpp") is defined.

  1. Getter Methods: These are methods used to get or retrieve the value of private attributes. Here, methods getStreet(), getCity(), getState(), and getZip() are defined to return the respective attribute values. The const keyword at the end of these methods signifies that these methods won't modify the object's state.

  2. Setter Methods: These methods are used to set or change the value of private attributes. setStreet(), setCity(), setState(), and setZip() are defined to set the values of the respective attributes.

  3. Class Method:

    • print(): This method concatenates all the attributes into a single string and returns that string. It is used to get the whole address as a string in the required format.

  4. Constructors: These are special methods used to initialize objects of a class.

    • Parameterized constructor (Address(string, string, string, string)): This constructor is used to initialize an Address object with specific values for street, city, state, and zip.

    • Default constructor (Address()): This constructor initializes an Address object with default values ("NA" in this case).

    • Copy constructor (Address(const Address&)): This constructor creates a new Address object that is a copy of an existing Address object. It copies the values of street, city, state, and zip from the source object to the new object.

This class implements the concept of Encapsulation, where the data (attributes) of a class are hidden from outside classes and can only be accessed through public methods (getters and setters). This protects the data from being changed accidentally and provides control over how it's accessed or modified. It's a key principle of Object-Oriented Programming (OOP).

Person header File

// // Person.hpp // Created by Kevin Roark on 6-15-23. #ifndef Person_hpp #define Person_hpp #include <stdio.h> #endif /* Person_hpp */ #include <string> #include "Address.hpp" using namespace std; class Person { private: //class attributes / properties string firstName; string middleName; string lastName; Address homeAddress; public: //getters and setters declarations void print() const; void setName(string first, string middle, string last); void setLastName(string last); void setFirstName(string first); void setMiddleName(string middle); void setAddress(Address myAddress); string getFirstName() const; string getMiddleName() const; string getLastName() const; Address getAddress() const; //constructor Person(string, string, string, Address ); };

This is the header file for the Person class. The class defines a Person object with private attributes for first, middle, and last names, and their address. The class provides public methods (getters and setters) to access and modify these attributes. It also provides a constructor to initialize a Person object with specific values.

  1. Class attributes: These are the properties of the Person class.

    • firstName, middleName, and lastName are of type std::string and represent the person's first, middle, and last names respectively.

    • homeAddress is of type Address (another class defined in "Address.hpp"). It is used to store the person's address.

  2. Getters and Setters: These methods provide a way to read and write the private attributes of the class.

    • setFirstName(string first), setMiddleName(string middle), setLastName(string last): These methods set the first, middle, and last names of the person.

    • setName(string first, string middle, string last): This method sets all the names (first, middle, and last) at once.

    • setAddress(Address myAddress): This method sets the homeAddress attribute.

    • getFirstName() const, getMiddleName() const, getLastName() const: These methods return the first, middle, and last names of the person.

    • getAddress() const: This method returns the homeAddress of the person.

  3. print() method: This method is used to print the details of the Person object. The implementation of this method should be in the corresponding .cpp file.

  4. Constructor: The constructor (Person(string, string, string, Address)) is a special method that is called when an object of the Person class is created. It initializes the Person object with specific values for first name, middle name, last name, and address.

This class showcases the concept of aggregation, where the Address class is used as an attribute in the Person class. An object of the Person class has an object of the Address class as part of its state. This is a form of "has-a" relationship (a Person has an Address), one of the fundamental relationships in object-oriented design.

Code file for Person

This is the implementation file for the Person class declared in "Person.hpp". Here, all the member functions (or methods) declared in the Person class are defined. This includes the constructor, getters, setters, and the print function.

  1. Constructor: The constructor Person::Person(string first, string middle, string last, Address homeAdd) is defined to initialize the attributes of a Person object with provided values when it is created.

  2. Setters: These functions set the values of the respective private attributes of the Person class.

    • Person::setName(string first, string middle, string last) sets the first name, middle name, and last name at once.

    • Person::setFirstName(string first), Person::setMiddleName(string middle), Person::setLastName(string last) set the first, middle, and last names individually.

  3. Getters: These functions return the values of the respective private attributes.

    • Person::getFirstName() const, Person::getMiddleName() const, Person::getLastName() const return the first name, middle name, and last name, respectively.

    • Person::getAddress() const returns the homeAddress of the person.

  4. print function: The Person::print() const function prints the full name of the person (first, middle, and last names) on one line and then prints the address on the following lines. It uses the print function of the Address class to print the address.

This file provides the implementations of the functions declared in the Person class, and demonstrates how a Person object can use the Address class through aggregation. In this case, Person has a member homeAddress of type Address, which can be used to store and manipulate the address details of a Person object.

 

Driver Program

 

This is the main program that utilizes the Person and Address classes to create a Person object with address information and then print the details.

Let's break it down:

  1. #include <iostream>: This line includes the standard C++ library for input/output operations.

  2. #include "Person.hpp": This line includes the header file for the Person class, which contains the class definition.

  3. using namespace std;: This line allows for the use of standard library functions without having to prepend them with std::.

  4. int main(): This is the main function where the program execution begins.

  5. Inside the main function:

    • Address home("1 Donore Square", "San Antonio", "Texas", "78229");: Here, an object of the Address class is created named home, and it is initialized with the given values.

    • Person myPerson("Kevin", "Read", "Roark", home);: Here, an object of the Person class is created named myPerson, and it is initialized with the given values and the home object created above. This is an example of aggregation as the Address object is part of the Person object.

    • myPerson.print();: This line calls the print method on the myPerson object, which will print the first name, middle name, last name and the address (by invoking the print method of the Address class).

    • cout << endl;: This line simply prints a new line to the console for cleaner output formatting.

    • return 0;: This line signifies successful termination of the program.

This program is a simple demonstration of creating objects in C++ using user-defined classes, specifically showcasing the concept of aggregation, where one class (Person) is using another class (Address) as a data member.

2024 - Programming 3 / Data Structures - Author: Dr. Kevin Roark