It is common for a C++ class to have objects of other C++ classes as data members. For example, we might define a Course
class to encapsulate a collection of students. The new Course
could have an array of Student
objects as one of its data members. This relationship between a Course
object and the Student
objects that are its data members is called a "has a" relationship. A Course
object "has" an array of Student
objects.
This has some obvious advantages over simply creating an array of Student
objects as a local variable of a function. We can include additonal state information in the Course
class, such as the course name and number. We can create additional courses simply by declaring additional Course
objects.
Here is a full program example illustrating the creation and use of Student
and Course
objects:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <string>
using std::cerr;
using std::cout;
using std::endl;
using std::fixed;
using std::ifstream;
using std::setprecision;
using std::string;
// Student class definition
class Student
{
private:
char name[31]{"None"};
double gpa{0.0};
public:
// Constructors
Student() = default;
Student(const char*, double);
// Accessor and mutator member functions
void set_name(const char*);
const char* get_name() const;
void set_gpa(double);
double get_gpa() const;
// Other member functions
void print() const;
};
// Course class definition
class Course
{
private:
char name[31]{"None"};
char course_number[11]{"None"};
Student class_list[45];
int num_students = 0;
void sort_class_list();
public:
// Constructors
Course() = default;
Course(const char*, const char*);
// Other member functions
void read_student_data(const string&);
void print() const;
};
int main()
{
Course course1("CSCI 240", "Introduction to Programming");
Course course2("CSCI 241", "Intermediate Programming");
course1.read_student_data("students1.txt");
course1.print();
cout << endl;
course2.read_student_data("students2.txt");
course2.print();
return 0;
}
// Student constructor
Student::Student(const char* new_name, double new_gpa)
{
set_name(new_name);
set_gpa(new_gpa);
}
// Student accessor and mutator member functions
void Student::set_name(const char* new_name)
{
strcpy(name, new_name);
}
const char* Student::get_name() const
{
return name;
}
void Student::set_gpa(double new_gpa)
{
if (new_gpa < 0.0)
gpa = 0.0;
else if (new_gpa > 4.0)
gpa = 4.0;
else
gpa = new_gpa;
}
double Student::get_gpa() const
{
return gpa;
}
// Other Student member functions
void Student::print() const
{
cout << "Name: " << name << endl
<< "GPA: " << fixed << setprecision(2) << gpa << endl;
}
// Course constructor
Course::Course(const char* new_course_number, const char* new_name)
{
strcpy(name, new_name);
strcpy(course_number, new_course_number);
num_students = 0;
}
// Other Course member functions
void Course::read_student_data(const string& file_name)
{
ifstream in_file;
char first_name[11], last_name[21], name[31];
double gpa;
// Open the input file and test for failure
in_file.open(file_name);
if (!in_file)
{
cerr << "Error - unable to open input file " << file_name << endl;
exit(1);
}
in_file >> first_name;
while (in_file)
{
in_file >> last_name;
in_file >> gpa;
strcpy(name, last_name);
strcat(name, ", ");
strcat(name, first_name);
// Create a Student object and copy it into
// the array.
class_list[num_students] = Student(name, gpa);
num_students++;
in_file >> first_name;
}
in_file.close();
sort_class_list();
}
void Course::sort_class_list()
{
int i, j, min;
Student temp;
for (i = 0; i < num_students - 1; i++)
{
min = i;
for (j = i+1; j < num_students; j++)
{
if (strcmp(class_list[j].get_name(), class_list[min].get_name()) < 0)
min = j;
}
temp = class_list[i];
class_list[i] = class_list[min];
class_list[min] = temp;
}
}
void Course::print() const
{
int i;
cout << course_number << " " << name << endl << endl;
for (i = 0; i < num_students; i++)
{
class_list[i].print();
cout << endl;
}
}
Download the full program example, including a makefile and sample data files