/********************************************************************** * virtual.cc * Tom Kelliher * * This program demonstrates several advanced features of classes: * o Abstract base classes and pure virtual functions. * o Virtual functions, polymorphism, and late binding. * o Static class members. * o Friend functions. * * The program defines class person as an abstract base class. Class * employee is derived from this class, and class manager is derived * from class employee. * * All persons are linked together through the static data member list * of person. A print() member function must be defined for all * classes derived from class person. The function printList() * traverses the list, calling print() on each person in the list. * Because print() is virtual, it is polymorphic. **********************************************************************/ // Comment out the following #define to make printList() a member // function of class person. Otherwise, it will be a friend of class // person. #define FRIEND #include #include /********************************************************************** * class person **********************************************************************/ class person { #ifdef FRIEND friend void printList(void); #endif // Allow derived classes direct access. protected: char* name; int age; // Pointer to next person on list. person* next; // Head pointer to persons list. Because it is static, // all class variables *share* it. static person* list; public: person(char* name, int age); virtual void print(void) = 0; #ifndef FRIEND static void printList(void); #endif }; // Static class data members can only be initialized at file scope. person* person::list = NULL; /********************************************************************** * person::person() * * Preconditions: name is a string, age is a non-negative integer. * * Postconditions: Person is initialized with the given name and age. **********************************************************************/ person::person(char* name, int age) : name(name), age(age) { next = list; // Add the new person to the beginning of the list. list = this; } /********************************************************************** * printList() || person::printList() * * Preconditions: None. * * Postconditions: The list of persons is printed. **********************************************************************/ #ifdef FRIEND void printList(void) #else void person::printList(void) #endif { person* pp; for (pp = person::list; pp != NULL; pp = pp->next) pp->print(); } /********************************************************************** * class employee **********************************************************************/ class employee : public person { private: char* company; public: employee(char* company, char* name, int age); void print(void); }; /********************************************************************** * employee::employee() * * Preconditions: Company and name are strings, age is a non-negative * integer. * * Postconditions: The new employee is initialized. **********************************************************************/ employee::employee(char* company, char* name, int age) : person(name, age), company(company) { } /********************************************************************** * employee::print() * * Preconditions: None. * * Postconditions: The employee data is printed. **********************************************************************/ void employee::print(void) { cout << "Employee: " << name << endl; cout << "Company: " << company << endl; cout << "Age: " << age << endl << endl; } /********************************************************************** * class manager **********************************************************************/ class manager : public employee { private: char* dept; public: manager(char* dept, char* company, char* name, int age); void print(void); }; /********************************************************************** * manager::manager() * * Preconditions: Department, company, and name are strings, age is a * non-negative integer. * * Postconditions: The new manager is initialized. **********************************************************************/ manager::manager(char* dept, char* company, char* name, int age) : employee(company, name, age), dept(dept) { } /********************************************************************** * manager::print() * * Preconditions: None. * * Postconditions: The manager data is printed. **********************************************************************/ void manager::print(void) { cout << "Manager of department: " << dept << endl; employee::print(); } /********************************************************************** * main() **********************************************************************/ int main() { employee e("Amalagated Widgets", "Bob", 13); manager m("Widgets", "Amalagated Widgets", "Jane", 15); #ifdef FRIEND printList(); #else person::printList(); #endif cout << "**************************************************\n\n"; manager mm("Assorted Baubles", "Baubles, Inc.", "Tony", 3); employee ee("Baubles, Inc.", "Pam", 1); #ifdef FRIEND printList(); #else person::printList(); #endif }