Advanced Class Features, Round II

Tom Kelliher, CS23

Apr. 29, 1996

Final project: Project 25, pg. 554.

Quiz, on today's material (including lab), on Wednesday.

Schedule for remainder of semester:

Advanced Class Features

An Example

This program is on the homepage, and also available from ~kelliher/public_html/cs23/virtual.cc.

/**********************************************************************
 * 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 <iostream.h>
#include <stdlib.h>


/**********************************************************************
 * 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, only one
   // 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
}

Lab

Grab a copy of the program and try/answer the following:



Thomas P. Kelliher
Sun Apr 28 16:19:37 EDT 1996
Tom Kelliher