In real-life, complex objects are often built from smaller, simpler objects. You are built from smaller parts: a head, a body, some legs, arms, etc ... This process of building complex objects from simpler ones is called object composition.
Composition is used for objects that have/has a relationship to each other. A house has a door, has a roof, has a balcony. C++ allows us to do object composition in a very simple way by using classes as member variables in other classes. The classes, which those member variables belong to, called suppliers, the host or the client is the class that contains those member variables.
For Example:
We will write a class maintains employee information as following:
class Employee // maintain employee information
{
private:
// String (ID) and Date are supplier classes
String name; // employee ID (Supplier)
Date birthDate // date of birth (Supplier)
Date hireDate; // date of hire (Supplier)
public:
. . .
};
Notice:
- name is an object belongs to String data type (supplier).
- birthDate and hireDate are objects belong to Date class (supplier).
- Employee class contain name, birthDate and hireDate member variables (host).
- We have to define the supplier class before can use it in other classes.
So we have to define Date class before defining Employee class:
class Date {
public:
Date( int mn= 1, int dy= 1, int yr = 1900 ) // default constructor
{
if ( mn > 0 && mn <= 12 ) // validate the month
month = mn;
else
{
month = 1;
cout << "Month " << mn << " invalid. Set to month 1.\n";
}
year = yr; // should validate yr
day = checkDay( dy ); // validate the day
cout << "Date object constructor for date ";
print(); // interesting: a printwith no arguments
cout << endl;
}
void print() const; // print date in month/day/year format
{
cout << month << '/' << day << '/' << year;
}
~Date(); // provided to confirm destruction order
{
cout << "Date object destructor for date ";
print();
cout << endl;
}
private:
int month; // 1-12
int day; // 1-31 based on month
int year; // any year
// utility function to test proper day for month and year
// based on month and year.
// Is the year 2000 a leap year?
int checkDay( int testDay )
{
static const int daysPerMonth[ 13 ] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
return testDay;
if ( month == 2 && // February: Check for leap year
testDay == 29 &&
( year % 400 == 0 ||
( year % 4 == 0 && year % 100 != 0 ) ) )
return testDay;
cout << "Day " << testDay << " invalid. Set to day 1.\n";
return 1; // leave object in consistent state if bad value
}
};
Now we can define Employee class:
class Employee {
public:
Employee( char *, char *lname,
int bmonth, intbday, int byear,
int hmonth, inthday, int hyear )
: birthDate( bmonth, bday, byear ),
hireDate( hmonth, hday, hyear )
{
// copy fname into firstName andbe sure that it fits
int length = strlen( fname );
length = ( length < 25 ? length : 24 );
strncpy( firstName, fname, length );
firstName[ length ] = '\0';
// copy lname into lastName and be sure that it fits
length = strlen( lname );
length = ( length < 25 ? length : 24 );
strncpy( lastName, lname, length );
lastName[ length ] = '\0';
cout << "Employee object constructor: "
}
void print() const
{
cout << lastName << ", " << firstName << "\nHired: ";
hireDate.print();
cout << " Birth date: ";
birthDate.print();
cout << endl;
}
// Destructor: provided to confirm destruction order
Employee::~Employee()
{
cout << "Employee object destructor: "
<< lastName << ", " << firstName << endl;
}
private:
char firstName[ 25 ];
char lastName[ 25 ];
const Date birthDate;
const Date hireDate;
};
Now we can use above classes in Main function:
int main()
{
Employee e( "Bob", "Jones", 7, 24, 1949, 3, 12, 1988 );
cout << '\n';
e.print();
cout << "\nTest Date constructor with invalid values:\n";
Date d( 14, 35, 1994 ); // invalid Date values
cout << endl;
return 0;
}
The output:
Date object constructor for date 7/24/1949
Date object constructor for date 3/12/1988
Employee object constructor: Bob Jones
Jones, Bob
Hired: 3/12/1988 Birth date: 7/24/1949
Test Date constructor with invalid values:
Month 14 invalid. Set to month 1.
Day 35 invalid. Set to day 1.
Date object constructor for date 1/1/1994
Date object destructor for date 1/1/1994
Employee object destructor: Jones, Bob
Date object destructor for date 3/12/1988
Date object destructor for date 7/24/1949
Note: You can find the full source code of this example in code.zip file.