public
, private
, and protected
Aggregation's weak binding, implemented with class-scope pointer variables, affords us more options for building and maintaining a relationship than composition. But it also burdens us with the necessity of validating the pointers before using them and carefully managing dynamic memory to prevent a memory leak. Like composition, aggregation does not circumvent the access restrictions imposed by the private
and protected
keywords. So, programmers access these restricted part-class features through the class's public interface. The following examples demonstrate the whole class sending messages to (i.e., calling public
functions in) their part classes. In an aggregation relationship, we send a message to a part object using the pointer variable name, the arrow operator, and the message or function name.
class Part { private: int member; public: void display() // (a) { cout << member << endl; } }; |
class Whole
{
private:
Part* my_part = nullptr; // (b)
public:
void display() // (c)
{
if (my_part != nullptr) // (d)
my_part->display();
}
}; |
private
features.nullptr
, either in the class specification or the constructor.
class Address { private: string city; string state; public: Address(string c, string s) : city(c), state(s) {} void display() { cout << city << ", " << endl; } }; class Person { private: string name; Address* addr = nullptr; // (a) public: Person(string n, string c, string s) : addr(new Address(c, s)), name(n) // (b) Person(string n) : addr(nullptr), name(n) {} // (c) void display() { cout << name << end; if (addr != nullptr) // (d) addr->display(); // (e) } void setAddress(string c, string s) { if (addr != nullptr) // (f) delete addr; addr = new Address(c, s); // (g) } }; class Student : public Person // (h) { private: double gpa; public: Student(string n, double g, string c, string s) : Person(n, c, s), gpa(g) {} // (i) void display() { Person::display(); // (j) cout << gpa << endl; } } |
|
|
Student valedictorian("Alice", 4.0, "Ogden", "Utah"); valedictorian.display();
class Pet { private: string name; string vaccinations; public: Pet(string n, string v) : name(n), vaccinations(v) {} void display() { cout << name << " " << vaccinations << endl; } }; class Person { private: string name; string phone; public: Person(string n, string p) : name(n), phone(p) {} void display() { cout << name << endl; cout << phone << endl; } }; class Owner : public Person // (a) { private: int account; Pet* my_pet = nullptr; // (b) public: Owner(string n, string p, int a, string pn, string v) : Person(n, p), // (c) my_pet(pn, v), account(a) {} // (d) void display() { Person::display(); // (e) cout << account << endl; if (my_pet != nullptr) my_pet->display(); // (f) } }; |
|
|
Owner pet_owner("Dilbert", "801-555-1234", 123456, "Fido", "2020/06/01"); pet_owner.display();