1. Modeling the Aggregation Relationship in the Object Model

In this section we will look at aggregation, the "part of" connection. We will look at "what is aggregation?", how to identify aggregation, how to show aggregation on a class diagram, how to specify aggregation, and how to code aggregation.

  1. What is Aggregation?

Aggregation is a link between objects that is a strong association with "part of" semantics. Aggregation is a form of association and is sometimes referred to as "strong association". An aggregation relationship may be described as "part of" or "bill of materials" between an assembly object and part objects. For example a car "has a part" motor as shown in the figure below.

Figure Drawing showing aggregation.

An aggregation association has a cardinality or multiplicity. This is the number of objects on one side of an aggregation that may be associated with an object on the other side of the aggregation. For example, a car has one motor. This is an example of a 1 to 1 aggregation. The aggregation symbol is a diamond with a solid line between classes with the cardinality shown on each end of the solid line as shown in the figure below.

which shows the following as discussed in [Rumbaugh-91]:

antisymmetric (if A is part of B, then B is not part of A),

propagation (sharing of common operations and attribute values from the assembly to the part possibly with modification). Propagation refers to the automatic triggering of operations in part objects.

  1. Identifying Aggregation

Identify aggregation by looking for assembly and part objects. For example, a car is an assembly with a motor part. Look for objects that cannot exist without other objects. For example, an invoice cannot exist without a product line item. Look for objects that are so closely associated that they are destroyed if the first object is destroyed. For example, if an invoice is destroyed then the product line items are destroyed. The key questions to find an aggregation relationship from [Rumbaugh-91] are as follows:

Would you use the phrase "part of"? A paragraph is "part of" a chapter.

Are some operations on the whole automatically applied to its parts? Copy applies to chapter and paragraph.

Are some attribute values from the whole applied to all or some parts? Chapter title applies to paragraph.

Is there intrinsic asymmetry where one object is subordinate to other objects? A paragraph is subordinate to a chapter.

An aggregation relationship requires defining additional semantic rules particularly for the creation, copy, and deletion of objects. For example, do you automatically delete the part when the assembly is deleted?

  1. Showing Aggregation on the Class Diagram

Aggregation is shown on the class diagram by connecting assembly and part classes. The figure below is a class diagram showing aggregation using a CASE tool.

Figure Class diagram showing aggregation.

This diagram in the figure below shows the aggregation relationship between two classes. The car class is the assembly class. The motor class is the part class. The car class and the motor class have the same named operations. However the operate operation has different parameters in the car and motor classes. In aggregation, operations in the assembly object may be propagated to a part object. Propagation means automatic triggering (invoking) an operation from one object to another object. For example, a message to invoke the operate operation in a car object will propagate (trigger) to invoke the operate operation in the motor object.

The steps to create the class diagram showing aggregation using a CASE tool are as follows:

>> Run the CASE tool and show the tool bar or pull down menu.

>> Select and place a class symbol for the assembly class.

>> Select and place a class symbol for the part class.

>> Select the cardinality (multiplicity) on each side of the relationship, such as 1 to Many.

>> Select the aggregation relationship symbol and connect the two classes.

>> For C++ code generation, enter an object name for the traversal path name to represent the aggregation.

  1. Specifying the Aggregation Relationship

Each aggregation relationship should be described in a relationship specification form. Constraints (limitations and rules) should be stated. For aggregation multiplicity constraints should be stated. The semantics of part deletion and the propagation of operations and attribute values should be stated. The following is a sample relationship specification report created in a text editor.

Relationship Specification Report

- Source Class - Car

- Destination Class - Motor

- Traversal Path Class/Type and Name - Motor currentMotor

- Order by Attribute Class/Type and Name - N/A

- Type of Relationship (Association/Aggregation) - Aggregation

- Relationship Constraints (rules) - motor weight must be less than total car weight

- Relationship Cardinality - 1 to 1

- Inverse Traversal Path Class/Type and Name - Car currentCar

- Implementation - currentMotor data member implements the aggregation relationship between Car class and Motor class. The inverse relationship is implemented with currentCar as a pointer to the Car object.

- Remarks.

  1. Coding 1 to 1 Aggregation in C++

Once the class diagram has been completed, then C++ code can be automatically generated with a CASE tool. The CASE tool implements each aggregation shown on the class diagram. We are presenting how to code aggregation in C++ to be able to understand and modify the generated C++.

  1. Minimum C++ Code for 1 to 1 Aggregation

As discussed in the association section, there are many ways to code association and aggregation in C++. Aggregation is a special form of association. Ways to code aggregation include coding assembly class data members to hold part objects, pointers to part objects, or objects of special aggregation classes. The most straight forward way to code aggregation is to identify a traversal path name. A traversal path name is a reference to one or more part objects. A traversal path name is an assembly class data member that may hold one of the following: a part object, a collection of part objects, a pointer to a part object, or a pointer to a collection of part objects.

To code the aggregation relationship, identify a traversal path name to represent the aggregation. The traversal path name becomes a data member in the assembly class. In the simplest case a car has 1 motor. In the Car class identify a traversal path name for the 1 to 1 association with the Motor Class. The traversal path name in the Car class might be Motor currentMotor. In C++ code, create a data member for the traversal path name, such as currentMotor as an automatic C++ object. An automatic part object is deleted automatically when the assembly object is deleted. Alternatively create a dynamic object and manually delete the part object when the assembly object is deleted. The following is the form to create a data member for a part object: <Part Class Name> <Traversal path name>. The following is an example: Motor currentMotor.

An automatic object is used in this case because a part object generally does not exist independently of the assembly object. When the assembly is deleted, then the part is automatically deleted. For example, a motor object is automatically deleted when the car object is deleted.

Based upon the diagram in the figure below, the following C++ code was generated to show the aggregation relationship.

Figure Car class diagram showing 1 to 1 aggregation.

Listing C++ code listing showing 1 to 1 aggregation.

C++ Minimum Class Declarations with 1 : 1 Aggregation - Header Files

//////////////////////////Car.h file////////////////////////////////////

#ifndef __CAR_H

#define __CAR_H

#ifndef __MOTOR_H

#include "Motor.h"

#endif

class Car

{ int speed; //Attribute data member

Motor currentMotor; //1:1 aggregation part data member

public:

Car () : speed(0)

{

}

void operate (int aSpeed) ;

~ Car ( ) { } //Destructor

};

#endif

//////////////////////////Motor.h file////////////////////////////////////

#ifndef __MOTOR_H

#define __MOTOR_H

class Motor

{ int rpm; //Attribute data member

public:

Motor () : rpm(0) { }

void operate (int aRPM) ;

~ Motor ( ) { } //Destructor

};

#endif

C++ Source Code File

//////////////////////////Car.cpp file////////////////////////////////////

#include "Car.h"

void Car::operate(int aSpeed)

{ speed = aSpeed;

int rpm;

rpm = 100 * aSpeed;

currentMotor.operate (rpm); //message to invoke currentMotor.operate

}

//////////////////////////Motor.cpp file////////////////////////////////////

#include "Motor.h"

void Motor::operate(int aRPM)

{ rpm = aRPM);

}

C++ Main Function

//////////////////////////main.cpp file////////////////////////////////////

#include "Car.h"

int main ()

{

Car car1; //invokes the default constructor

car1.operate (55);

return 0;

}

  1. Minimum C++ Code Generation Scripts for 1 to 1 Aggregation

To generate the C++ class declaration with data member declarations, we used two scripts. A class declaration script generated the Car.h file and a function definition script generated the Car.cpp file. We created the main.cpp manually. The two scripts are shown below.

Script to Generate the C++ Minimum Class Declaration with 1 : 1 Aggregation

//////////////////////////TRUNCATE_EIGHT$CLASS_NAME.h file////////////////////////////////////

#ifndef __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

#define __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

[

#ifndef __$CAPITALIZE_ALL$TRUNCATE_EIGHT$AGGREGATION_ONE_CLASS$_H

#include "TRUNCATE_EIGHT$AGGREGATION_ONE_CLASS$.h"

#endif

]

class CLASS_NAME[NO_RETURN NO_REPEAT: NO_REPEAT public BASE_CLASS ,DELETE_LAST_SYMBOL]

{ [CPP_ATTRIBUTE_STATIC CPP_ATTRIBUTE_CONSTANT ATTRIBUTE_TYPE ATTRIBUTE_NAME$; //Attribute data member]

[AGGREGATION_ONE_CLASS AGGREGATION_ONE_NAME$; //1:1 aggregation part data member]

public:

CLASS_NAME ()

SELECT_WHEN LOGICAL_NOT ATTRIBUTE_IS_STATIC [NO_RETURN NO_REPEAT: ATTRIBUTE_NAME(ATTRIBUTE_INITIAL_VALUE),DELETE_LAST_SYMBOL]

}

[ CPP_OPERATION_VIRTUAL CPP_OPERATION_STATIC OPERATION_RETURN_TYPE OPERATION_NAME (CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT CPP_OPERATION_PURE_VIRTUAL;

]

OPERATION_CPP_VIRTUAL_BASE_CLASS ~ CLASS_NAME ( ) { } //Destructor

};

#endif

Script to Generate the C++ .cpp file

//////////////////////////TRUNCATE_EIGHT$CLASS_NAME.cpp file////////////////////////////////////

#include "TRUNCATE_EIGHT$CLASS_NAME.h"

[

OPERATION_RETURN_TYPE CLASS_NAME::OPERATION_NAME(CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT

{

OPERATION_CODE

}]

In this example, the CASE tool generated the class declarations (.h files) for the car class and the motor class. In the car class header file (car.h), it generated the include directive to include the header file of the part class (motor.h). In the car class declaration, it generated a private data member, currentMotor, to hold an object of the motor class. It generated the constructor.

The assembly object may initialize part objects in the constructor with an initializer list. If the initializer list is not provided then the part object constructor is implicitly invoked. Sample constructors are:

Car () { } //Part object constructor implicitly invoked

Car(): currentMotor () {}//Constructor with initializer list to explicitely

//initialize car and motor

If the part object is a dynamic object created with a new statement, then the assembly object must delete the part object in the destructor. A sample destructor to delete a dynamic part object aWindShieldWiper is

~Car () { delete aWindShieldWiper; }

  1. Enhanced C++ Code for 1 to Many Aggregation

To code C++ classes with 1 to 1 aggregation, create a class declaration and function definitions as shown in the diagrams below. Key aspects of the class declaration are shown on the left. This information class diagram shows that a aggregation assembly class declaration should have an include statement for the aggregation part class header file, a class name, data members, traversal data members holding an aggregation part object, a constructor, traversal function members to access aggregation part object, traversal data member accessor functions, function members, and a destructor. This information class diagram shows that the aggregation assembly class is connected to the aggregation part class with the traversal data member. The traversal data member is used to access the aggregation part object. The class diagram on the right shows sample C++ identifiers that are also in the code listings.

Figure Class diagram showing 1 to 1 aggregation

Key aspects of coding an aggregation assembly class are listed below. The aggregation assembly class is responsible to create and delete aggregation part objects.

- Declare a #include compiler directive to include the aggregation part class, e.g. #include "Motor.h".

- Declare an aggregation part data member (traversal data member) to implement to aggregation relationship, e.g. Motor currentMotor;

- Define a default constructor to initialize an object with default data member values in the initializer list. Aggregation part data member is automatically created. Car ()

- Define a constructor with arguments to initialize an object with passed values. Optionally, pass an aggregation part object and assign aggregation part data member. Car (int aSpeed, Motor& currentMotor) : speed (aSpeed), currentMotor (currentMotor) { }

- Define a copy constructor to initialize a object with a copy of another object. Must assign the aggregation part data member. Car (const Car& aCar) {currentMotor = aCar.currentMotor; }

- Define an assignment operator (operator=) to assign one object to another. Must assign the aggregation part data member. Car& operator= (const Car& aCar) {currentMotor = aCar.currentMotor; }

- Define an equality operator (operator==) to compare two objects. Must compare the aggregation part data members. int operator== (const Car& aCar) { return (currentMotor == aCar.currentMotor) ; }

- Define input function - C++ insertion operator for use with cin. Must invoke the aggregation part object operator>> e.g. friend istream& operator>> (istream& is, Car& aCar) {is >> aCar.currentMotor; }

- Define the output function - C++ extraction operator for use with cout. Must invoke the aggregation part object operator<<, e.g. friend ostream& operator<< (ostream& os, Car& aCar) { os << aCar.currentMotor; }

- Define get and set assessor functions, e.g. Motor& getCurrentMotor () { return currentMotor; } Warning - returning a reference provides direct access to a private data member, e.g. car1.getCurrentMotor() = newMotor;

- Define a traversal function to access the aggregation part data member, e.g. void operate ()which invokes currentMotor.operate().

- Define a default destructor to deinitialize an object, ~Car () {}

- Define a main (test) function to create an aggregation assembly object with a part object and invoke a traversal function

In coding the aggregation part class, optionally declare an inverse traversal data member, e.g. Car * aCar; Prior to compiling the aggregation part class, insert a forward declaration before the aggregation part class declaration, e.g. class Car; The complete C++ code listing is below.

Listing C++ Code Listing for 1 to 1 Aggregation

C++ Class Declaration with 1 to 1 Aggregation - Header File

// Class: Car //ANSI C++

#ifndef __CAR_H //Required for Car class

#define __CAR_H

#ifndef __IOSTREAM_H //Required for cin and cout

#include <iostream.h>

#endif

#ifndef __CSTRING_H //Required for CString class

#include <CString.h>

#endif

//Required for 1:1 aggregation (part) classes

#ifndef __MOTOR_H //Motor

#include "Motor.h"

#endif

class Car

{ int speed; //Attribute data member

Motor currentMotor; //1:1 aggregation part data member

public:

//Default constructor alternative to compiler provided default constructor

//Ensure correct initial values

//Initialization list has members in the order declared

//Association object data member pointers initialized to null association object

Car ();

//Constructor with arguments

//Update to argument list to initialize base class data members,

//e.g. (int aNumber) : BaseClass (aNumber)

Car ( int aspeed ) ;

//Copy Constructor

Car (const Car& aCar );

//Operator= Assignment Operator

Car& operator= (const Car& aCar);

//Operator== Equality Operator

int operator== (const Car& aCar) const;

//Operator<< for cout

friend ostream& operator<< (ostream& os, const Car& aCar);

//Operator>> for cin

friend istream& operator>> (istream& is, Car& aCar);

//Get accessor function for non-static attribute data member

int getspeed() const

{ return speed;

}

//Set accessor function for non-static attribute data member

void setspeed (const int aspeed)

{ speed = aspeed;

}

//Get accessor function for 1:1 aggregation part data member

const Motor& getMotor() const

{ return currentMotor;

}

//Set accessor function for 1:1 aggregation part data member

void setMotor (const Motor& acurrentMotor)

{ currentMotor = acurrentMotor;

}

void operate (int aSpeed) ;

~ Car ( ) { } //Destructor - Delete any pointer data members that used new in constructors

//Destructor should be virtual if and only if class contains at least one virtual function

//Objects destroyed in the reverse order of the construction order

};

#endif

C++ Source Code File

//////////////////////////.cpp file/////////////////////////////////////////////////////

#include "Car.h"

void Car::operate(int aSpeed)

{ speed = aSpeed;

}

//Default constructor alternative to compiler provided default constructor

Car::Car ()

: speed(0)

{

}

//Constructor with arguments

//Update to argument list to initialize base class data members and const data members

//e.g. (int aNumber) : BaseClass (aNumber) , constMinimumValue (aMinimumValue)

Car::Car ( int aspeed )

{ speed = aspeed; //Initialization of attributes

}

//Copy constructor alternative to compiler provided default copy constructor

Car::Car (const Car& aCar )

{speed = aCar.speed;

currentMotor = aCar.currentMotor;

}

//Operator= Assignment Operator alternative to compiler provided operator=

Car& Car::operator= (const Car& aCar)

{ if (this == &aCar) return *this;

speed = aCar.speed;

currentMotor = aCar.currentMotor;

return *this;

}

//Operator== Equality Operator

int Car::operator== (const Car& aCar) const

{ return (

//Equality check for 1:1 aggregation part data members

( currentMotor == aCar.currentMotor) &&

//Equality check for attribute data members

(speed == aCar.speed)

);

}

//Operator<< extraction for cout

ostream& operator<< (ostream& os, const Car& aCar)

{ os << "Object Attribute Values - Class Car" << endl;

os << "speed: " << aCar.speed << endl;

os << " currentMotor: " << aCar.currentMotor << endl;

return os;

}

//Operator>> insertion for cin

istream& operator>> (istream& is, Car& aCar)

{ cout << "\nEnter Object Attribute Values or 0 - Class Car";

cout << "\nEnter speed : " << endl;

is >> aCar.speed;

is >> aCar.currentMotor;

return is;

}

  1. Coding 1 to Many Aggregation in C++
  2. Minimum C++ Code for 1 to Many Aggregation

In the 1 to many association identify a traversal path name that holds a collection of part objects. For example, a car has many wheels. In the car class identify a traversal path name, such as tireArray or currentTires. In C++ code, create a data member for the traversal path name, such as tireArray or currentTires. The following are several examples.

Tire tireArray[4]; //C++ array

List <Tire> currentTires; //C++ template class

A programmer may add and remove part objects from the collection of part objects. For example, the programmer may insert tire1 and tire2 to the collection. He may remove tire1 and tire2 from the collection.

Figure Car class diagram showing 1 to many aggregation.

Listing C++ code listing showing 1 to many aggregation.

C++ Minimum Class Declarations with 1 : M Aggegation - Header Files

//////////////////////////Car.h file////////////////////////////////////

#ifndef __CAR_H

#define __CAR_H

#ifndef __TIRE_H

#include "Tire.h"

#endif

const int maxNumberOfTires = 4;

class Car

{ int speed; //Attribute data member

int currentTiresIndex; //Index for array of 1:M aggregation part objects

//1:M aggregation part data member

//Change C array to C++ collection class with iterator

Tire currentTires [maxNumberOfTires ];

public:

Car () : speed(0)

{ currentTiresIndex = 0; //Index for array of 1:M aggregation part objects

}

void start () ;

~ Car ( ) { } //Destructor

};

#endif

//////////////////////////Tire.h file////////////////////////////////////

#ifndef __TIRE_H

#define __TIRE_H

class Tire

{ int pressure; //Attribute data member

public:

Tire () : pressure(0) { }

void checkTirePressure () ;

~ Tire ( ) { } //Destructor

};

#endif

C++ Source Code Files

//////////////////////////Car.cpp file////////////////////////////////////

#include "Car.h"

void Car::start()

{ int i = 0;

for ( i = 0; i < maxNumberOfTires; i++) currentTires[i].checkTirePressure();

}

//////////////////////////Tire.cpp file////////////////////////////////////

#include "Tire.h"

void Tire::checkTirePressure() {

}

C++ Main Function

//////////////////////////main.cpp file////////////////////////////////////

#include "Car.h"

int main ()

{

Car car1; //invokes the default constructor

car1.start();

return 0;

}

  1. Minimum C++ Code Generation Scripts for 1 to Many Aggregation

To generate the C++ class declaration with data member declarations, we used two scripts. A class declaration script generated the Car.h file and the function definition script generated the Car.cpp file. We created the main.cpp manually. The two scripts are shown below.

Script to Generate the C++ Minimum Class Declaration with 1 : M Aggregation - Header File

//////////////////////////TRUNCATE_EIGHT$CLASS_NAME.h file////////////////////////////////////

#ifndef __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

#define __$CAPITALIZE_ALL$TRUNCATE_EIGHT$CLASS_NAME$_H

[

#ifndef __$CAPITALIZE_ALL$TRUNCATE_EIGHT$AGGREGATION_MANY_CLASS$_H

#include "TRUNCATE_EIGHT$AGGREGATION_MANY_CLASS$.h"

#endif

]

NO_OUTPUT_BEGIN Use the the CLASS_USER fields for typedef, enum, const declarations, e.g.

const int maxNumberOfTires = 4; NO_OUTPUT_END

CLASS_USER1

CLASS_USER2

class CLASS_NAME[NO_RETURN NO_REPEAT: NO_REPEAT public BASE_CLASS ,DELETE_LAST_SYMBOL]

{ [CPP_ATTRIBUTE_STATIC CPP_ATTRIBUTE_CONSTANT ATTRIBUTE_TYPE ATTRIBUTE_NAME$; //Attribute data member]

[int AGGREGATION_MANY_NAME$Index; //Index for array of 1:M aggregation part objects]

[ //1:M aggregation part data member

//Change C array to C++ collection class with iterator

AGGREGATION_MANY_CLASS AGGREGATION_MANY_NAME LITERAL_SYMBOL[maxNumberOf$AGGREGATION_MANY_CLASS$s LITERAL_SYMBOL];]

[int ASSOCIATION_MANY_NAME$Index; //Index for array of 1:M association objects]

public:

CLASS_NAME ()

SELECT_WHEN LOGICAL_NOT ATTRIBUTE_IS_STATIC [NO_RETURN NO_REPEAT: ATTRIBUTE_NAME(ATTRIBUTE_INITIAL_VALUE),DELETE_LAST_SYMBOL]

{ [ASSOCIATION_ONE_NAME = &null$ASSOCIATION_ONE_CLASS; //Initialization to null association object ]

[AGGREGATION_MANY_NAME$Index = 0; //Index for array of 1:M aggregation part objects ]

}

[ CPP_OPERATION_VIRTUAL CPP_OPERATION_STATIC OPERATION_RETURN_TYPE OPERATION_NAME (CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT CPP_OPERATION_PURE_VIRTUAL;

]

OPERATION_CPP_VIRTUAL_BASE_CLASS ~ CLASS_NAME ( ) { } //Destructor

};

#endif

Script to Generate the C++ Function Definitions - .cpp File

//////////////////////////TRUNCATE_EIGHT$CLASS_NAME.cpp file////////////////////////////////////

#include "TRUNCATE_EIGHT$CLASS_NAME.h"

[

OPERATION_RETURN_TYPE CLASS_NAME::OPERATION_NAME(CPP_OPERATION_PARAMETERS) CPP_OPERATION_CONSTANT

{ OPERATION_CODE

}

]

  1. Enhanced C++ Code for 1 to Many Aggregation

Key aspects of the class declaration are shown on the class diagrams below. Key aspects of the class declaration are shown on the left. This information class diagram shows that an aggregation assembly class declaration should have an include statement for the aggregation part class header file, a class name, data members, traversal data members collection holding aggregation part objects, a constructor, traversal function members to access aggregation part object, traversal data member accessor functions, function members, and a destructor. This information class diagram shows that the aggregation assembly class is connected to the aggregation part class with the traversal data member collection. The traversal data member collection is used to access the aggregation part objects. The class diagram on the right shows sample C++ identifiers that are also in the code listings.

Figure Class diagram showing 1 to Many aggregation

Key aspects of coding a 1 to many aggregation assembly class are listed below. The aggregation assembly class is responsible to create and delete aggregation part objects.

- Declare an #include compiler directive to include the aggregation part class, e.g. #include "Tire.h". If required include the collection class holding aggregation part objects.

- Declare an aggregation part data member - array or collection object to implement to 1 to many aggregation relationship, e.g. Tire currentTires [maxNumberOfTires];

- Define a default constructor to initialize an object with default data member values. Array of aggregation part objects is initialized with default values. Car (){ }

- Define a constructor with arguments to initialize an object with passed values. Optionally pass a pointer to an array or collection object and assign the array or collection object. Optional iterator. Car (int aSpeed, Tire* pTires) { currentTires [0] = *pTires; }

- Define a copy constructor to initialize an object with a copy of another object. Must assign the array or collection object. Optional iterator. Car (const Car& aCar)

- Define an assignment operator (operator=) to assign one object to another. Must assign the array or collection object. Optional iterator. Car& operator= (const Car& aCar) {for (i = 0; i < maxNumberOfTires; i++) currentTires [i] = aCar.currentTires [i]; }

- Define an equality operator (operator==) to compare two objects. Must compare the array or collection object part. Optional iterator.

int operator== (const Car& aCar)

{ return ((currentTires [0] == aCar.currentTires [0])&& ;

(currentTires [1] == aCar.currentTires [1])) }

Note to compare two arrays == must be defined for array. Otherwise use element by element comparison.

- Define input function - C++ insertion operator for use with cin. Must invoke the aggregation part object operator>>. Iterator required. friend istream& operator>> (istream& is, Car& aCar) {for (i = 0; i < maxNumberOfTires; i++) is >> aCar.currentTires [i]; }

- Define the output function - C++ extraction operator for use with cout. Must invoke the aggregation part object operator<<. Iterator required. friend ostream& operator<< (ostream& os, Car& aCar) { for (i = 0; i < maxNumberOfTires; i++) os << aCar.currentTires [i]; }

- Define a get and set function for the collection of aggregation part objects, e.g. Tire* getCurrentTire () {return &currentTires[0];}

- Define getFirst and exists assessor functions for individual aggregation part objects, e.g. Tire& getFirstTire () {return currentTires[0];}

- Define a default destructor to deinitialize an object, ~Car () {}

- Define a main (test) function to create an aggregation assembly object with part objects and invoke a traversal function.

In the aggregation part class, optionally declare an inverse traversal data member, e.g. Car * aCar; Prior to compiling the aggregation part class, insert a forward declaration before the aggregation part class declaration, e.g. class Car.

The complete C++ code listing is below.

Listing C++ Code Listing for 1 to M Aggregation

C++ Class Declaration with 1 : M Aggregation - Header File

// Class: Car //ANSI C++

#ifndef __CAR_H //Required for Car class

#define __CAR_H

#ifndef __IOSTREAM_H //Required for cin and cout

#include <iostream.h>

#endif

#ifndef __CSTRING_H //Required for CString class

#include <CString.h>

#endif

//Required for 1:M aggregation (part) classes

#ifndef __TIRE_H //Tire

#include "Tire.h"

#endif

const int maxNumberOfTires = 4;

class Car

{ int speed; //Attribute data member

int currentTiresIndex; //Index for array of 1:M aggregation part objects

//1:M aggregation part data member

//Change C array to C++ collection class with iterator

Tire currentTires [maxNumberOfTires ];

public:

//Default constructor alternative to compiler provided default constructor

//Ensure correct initial values

//Initialization list has members in the order declared

//Association object data member pointers initialized to null association object

Car ();

//Constructor with arguments

//Update to argument list to initialize base class data members,

//e.g. (int aNumber) : BaseClass (aNumber)

Car ( int aspeed ) ;

//Copy Constructor

Car (const Car& aCar );

//Operator= Assignment Operator

Car& operator= (const Car& aCar);

//Operator== Equality Operator

int operator== (const Car& aCar) const;

//Operator<< for cout

friend ostream& operator<< (ostream& os, const Car& aCar);

//Operator>> for cin

friend istream& operator>> (istream& is, Car& aCar);

//Get accessor function for non-static attribute data member

int getspeed() const

{ return speed;

}

//Set accessor function for non-static attribute data member

void setspeed (const int aspeed)

{ speed = aspeed;

}

//Get accessor function for 1:M aggregation collection

const Tire* getTireCollection () const ;

//Set accessor function for 1:M aggregation collection

void setTireCollection (Tire* const acurrentTiresCollection);

//Get accessor function for 1:M aggregation part data member

const Tire& getFirstTire() const ;

//Exists function for 1:M aggregation part data member

int existsTire (const Tire& aTire) const ;

void start () ;

~ Car ( ) { } //Destructor - Delete any pointer data members that used new in constructors

//Destructor should be virtual if and only if class contains at least one virtual function

//Objects destroyed in the reverse order of the construction order

};

#endif

C++ Source Code File

//////////////////////////.cpp file/////////////////////////////////////////////////////

#include "Car.h"

void Car::start()

{

}

//Default constructor alternative to compiler provided default constructor

Car::Car ()

: speed(0)

{ currentTiresIndex = 0; //Index for array of 1:M aggregation part objects

}

//Constructor with arguments

//Update to argument list to initialize base class data members and const data members

//e.g. (int aNumber) : BaseClass (aNumber) , constMinimumValue (aMinimumValue)

Car::Car ( int aspeed )

{ speed = aspeed; //Initialization of attributes

currentTiresIndex = 0; //Index for array of 1:M aggregation part objects

}

//Copy constructor alternative to compiler provided default copy constructor

Car::Car (const Car& aCar )

{int i = 0;

currentTiresIndex = 0; //Index for array of 1:M aggregation part objects

speed = aCar.speed;

for ( i = 0; i < maxNumberOfTires; i++) currentTires [i ] = aCar.currentTires [i ] ;

}

//Operator= Assignment Operator alternative to compiler provided operator=

Car& Car::operator= (const Car& aCar)

{ if (this == &aCar) return *this;

int i = 0;

speed = aCar.speed;

for (i = 0; i < maxNumberOfTires; i++) currentTires [i ] = aCar.currentTires [i ] ;

return *this;

}

//Operator== Equality Operator

int Car::operator== (const Car& aCar) const

{ return (

//Equality check for 1:M aggregation parts

//Update for the correct number of aggregation part objects

( currentTires [0 ] == aCar.currentTires [0 ])&&

( currentTires [1 ] == aCar.currentTires [1 ])&&

( currentTires [2 ] == aCar.currentTires [2 ])&&

( currentTires [3 ] == aCar.currentTires [3 ])&&

//Equality check for attribute data members

(speed == aCar.speed)

);

}

//Operator<< extraction for cout

ostream& operator<< (ostream& os, const Car& aCar)

{ int i = 0;

os << "Object Attribute Values - Class Car" << endl;

os << "speed: " << aCar.speed << endl;

return os;

}

//Operator>> insertion for cin

istream& operator>> (istream& is, Car& aCar)

{ int i = 0;

cout << "\nEnter Object Attribute Values or 0 - Class Car";

cout << "\nEnter speed : " << endl;

is >> aCar.speed;

for (i = 0; i < maxNumberOfTires; i++) is >> aCar.currentTires [i ] ;

return is;

}

//Get accessor function for 1:M aggregation collection

const Tire* Car::getTireCollection () const

{ return currentTires ;

}

//Set accessor function for 1:M aggregation collection

void Car::setTireCollection (Tire* const aTireCollection)

{ for (int i = 0; i < maxNumberOfTires; i++) currentTires [ i ] = aTireCollection [ i ];

}

//Exists function for 1:M aggregation part data member

int Car::existsTire (const Tire& aTire) const

{ for (int i = 0; i < maxNumberOfTires; i++)

{ if ( currentTires [i ] == aTire ) return 1;

}

return 0;

}

//Get accessor function for 1:M aggregation part data member

const Tire& Car::getFirstTire() const

{ return currentTires [ 0 ] ;

}

  1. Coding C++ Classes with Inverse Relationships

Sometimes it is necessary to have relationships in two directions both in a forward direction and an inverse direction. Use attach and detach operations to provide access from the assembly to part objects. Additionally, attach and detach operations may be used to provide access from a part object to the assembly object for the inverse relationship. The figure below and listing below show an aggregation relationship between the Car class and the Motor class. There is an association relationship between the Motor class and the Car class. There is an inverse association relationship between the Car class and the Transmission class.

Figure Class diagram showing aggregation and association relationships.

Listing C++ code implementing aggregation and association relationships.

//Single file cartrans.cpp

#include "iostream.h"

class Car; //forward reference

class Transmission; //forward reference

------------------------Motor Class --------------------------------

class Motor {

Car *aCar;

Transmission *aTransmission;

public:

void operate () ;

void attachToCar (Car &currentCar);

void attachToTransmission (Transmission &currentTransmission);

};

void Motor::operate () {int aNumber = aCar->getCarID ();

cout << "The car number is " << aNumber << ".\n";

cout << "The motor is operating.\n";

aTransmission -> operate ();}

void Motor::attachToCar (Car &currentCar) { aCar = &currentCar;}

void Motor::attachToTransmission (Transmission &currentTransmission)

{aTransmission = &currentTransmission;}

------------------Transmission Class -------------------------------

class Transmission {

public:

void operate () {cout << "The transmission is operating.\n";};

};

-------------------------Car Class----------------------------------

class Car {

int carID;

Motor currentMotor;

Transmission aTransmission;

public:

int getCarID () {return carID;}

Car ();

void operate ();

};

Car::Car () {carID = 0;}

void Car::operate () {currentMotor.attachToCar (*this);

currentMotor.attachToTransmission (aTransmission); currentMotor.operate (); }

---------------------------Main Function----------------------------

int main () {

Car car1;

car1.operate ();

return 0;

}

//Sample Output

//The car ID is 0.

//The motor is operating.

//The transmission is operating.

  1. Modeling Aggregation for Quality Software

How we model aggregation can affect the quality of the software in terms of correctness, reliability, extendibility, and reusability. For example, the use of aggregation leads to "black box" modules that can be easily modified or changed out without affecting other modules. This improves the extendibility of the software. Aggregation supports encapsulation in which an assembly object hides the part objects.

The use of aggregation with propagation of operations is a software quality technique. It supports the creation of understandable, extendible software. One of the important aspects of aggregation is the automatic propagation (triggering) of operations from an assembly object to a part object. Once we have identified the operations in an assembly class, then these named operations may be identified in the part classes. The assembly object acts as a boss telling the part objects, the workers, what to do. Actual work and calculations are done in part objects.

Aggregation supports strong cohesion. The assembly object groups together related part objects. All the part objects support the purpose of the assembly object. We can check to ensure that there are no excessive or out-of-place part objects.

  1. Summary

In O-O modeling it is important to identify and describe relationships between classes and between objects. A relationship is a link or connection between classes or between objects. The association relationship is the "has a" relationship. The aggregation relationship is the "part of" relationship. Aggregation is a special form of association with special semantics (rules) for deletion and propagation of operations. Relationships are shown on the class diagram. Relationships may be specified in a relationship specification. Using a CASE tool, a class diagram showing relationships between classes may be created. The CASE tool may generate source code to implement the classes and the relationships.

cialis link tw886to generic cialis prices best price viagra cialis cialis attorney cincinnati cialis lowest price generic cialis trial packs black buy casino cialis diet followup gambling health jack phentermine poker post viagra cialis and bodybuilding cialis medication free generic cialis samples black buy casino cialis diet followup gambling jack online order phentermine poker post viagra cialis black box cialis message boards generic cialis american express apotheke cialis cialis and levitra and viagra and generic cialis muscle ache generic cialis hong kong archive blog cialis inurl cialis and levitra cialis line mexico does cialis work for women allowed black buy casino cialis diet holdem jack online order phentermine poker tag texas viagra xhtml cialis and multiple coitus cialis no prescription generic cialis price best for premature ejaculation viagra cialis levitra cialis and women cialis link liracrogreekbostoncom generic cialis allowed casino cialis diet phentermine poker tag viagra xhtml cialis add url cialis lawyer ohio experience cialis without ed allowed cialis phentermine tag viagra xhtml cialis back pain cialis online order how to get free cialis sample black buy casino cialis diet gambling jack order phentermine poker tag viagra xhtml cialis discount cialis maximum dose international order for generic cialis blogid buy casino cialis generic inurl order phentermine poker viagra cialis and blood pressure cialis mexico is cialis for me blogid buy casino cialis inurl phentermine poker viagra cialis and grapefruit cialis levitra viagra discount cialis best buy cialis generic ciales rock climbing cialis international shipping does cialis or levitra work best for diabetics allowed black buy casino cialis diet health jack phentermine poker sex tag title viagra xhtml cheap viagra cialis cialis lawyer cincinnati effectiveness of cialis reported allowed black casino cialis diet gambling jack phentermine poker tag viagra xhtml cheapest and cialis and generic and lowest price cialis injury attorney ohio compare levitra and cialis add cialis link suggest catholic cult and cialis cialis lcos lily online free cialis approval cialis fda cialis and early ejaculation cialis levitra viagra interaction generic cialis cheap free shipping free consultation articles on cialis cheapest cialis cialis injury lawyer columbus generic cialis international shipping buy cheapest cialis cialis compare levitra viagra cialis line prescription generic cialis next day black buy casino cheap cialis diet followup gambling health jack online order phentermine poker post viagra ciales cialis international shipping contact number cialis add buy cialis url cialis 20mg tablet cialis liquid how long does cialis take to work black buy casino cialis diet gambling health jack phentermine poker tag viagra xhtml cialis and alcohol cialis lawyer cleveland effectiveness viagra cialis levitra allowed casino cialis phentermine tag viagra xhtml cheapest cialis free samples cialis levitra versus versus viagra fda pharmaceutical testing trials cialis anti cialis impotence cheapest cialis price cialis injury attorney columbus compare viagra cialis and levitra add cialis site cheapest cialis with no perscription cialis injury lawyer cleveland compare viagra to cialis achat ligne cialis cheap cialis link suggest cialis impotence drug cialis with no prescription add buy cialis site canada cialis online cialis information prescribing cialis viagra taken together where can i buy cialis online black buy casino cialis diet followup gambling jack order phentermine poker post viagra cialis blindness cialis link suggest diabeties viagra cialis levitra allowed black buy casino cialis diet gambling jack order phentermine poker tag viagra xhtml cheap cialis online cialis generic tadalafil cialis without prescriptions add cialis generic link cialis and levitra taken together cialis information clinical trial testing cialis for high blood preasure add cialis link online canada generic cialis cialis germany cialis strength time line to buy without prescription cialis or levitra in detrit area buy cialis submit=buy cialis cialis drug interaction cialis online liquid cialis black buy casino cialis diet followup gambling jack low online order phentermine poker viagra cialis attorney cleveland cialis injury lawyer cincinnati cialis vs viagra .. can you take cialis with viagra cialis home page cialis western open ticket add buy cialis link canada cialis generic cialis generic online cialis uprima viagra value pharmaceuticals cialis buy cialis order cialis eli lilly cialis pharmacy natural supplement like cialis