Consider the following class from Stroustrup
#include "mystring.h"
class Employee {
public:
Employee(const char * name="John Q Public");
void print() const;
string full_name() const
{return first_name+" "+middle_initial+" "+family_name;}
\\ . . .
private:
string first_name, family_name;
char middle_initial;
\\ . . .
};
This is a simple class that describes the basic information we want to associate with an employee. It may be the case that for different types of employees, we want to redefine or add to the data. For example, if we have a manager, we might want to maintain a level indicator and a list of supervised employees in addition to the name information. We can just duplicate the class information in the manager class appending our additional information:
#include "mystring.h"
class Manager {
public:
Manager(const char * name="Jane M Doe", int l=1);
void print() const;
string full_name() const
{return first_name+" "+middle_initial+" "+family_name;}
\\ . . .
private:
string first_name, family_name;
char middle_initial;
int level;
Employees *supervised;
\\ . . .
};
But this gives some problems:
We can fix the second bullet by including a specific element of type Employee in the Manager class, but this does little for the first bullet, i.e.
#include "mystring.h"
class Manager {
public:
Manager(const char * name="Jane M Doe", int l=1);
void print() const;
string full_name() const
{return first_name+" "+middle_initial+" "+family_name;}
\\ . . .
private:
Employee me;
int level;
Employees *supervised;
\\ . . .
};
But this does not address the first bullet - the Manager is still not recognized as an Employee.
To capture these types of relationships and to allow related objects to be interchanged when addressing their common components, C++ provides for classes to inherit behavior. A class which inherits data from another class is known as a derived class. The class from which inheritance is obtained is the base class. A derived class may act as the base class for another class. In the following version of the manager, inheritance is used to provide the Employee data.
#include "mystring.h"
class Manager:public Employee {
public:
Manager(const char * name="Jane M Doe", int l=1);
void print() const;
\\ . . .
private:
int level;
Employees *supervised;
\\ . . .
};
Manager::Manager(const char *name, int l):Employee(name), level(l)
{
}
Manager::print() const{
cout << first_name << endl; // Error
}
void f(Employee e) {
}
void g(Manager m) {
}
int main()
{
Manager magoo;
Employee diane;
diane = magoo; // Legal
magoo = diane; // Error
f(magoo); // Legal
g(diane); // Error
}
Employee::print() const
{
cout << full_name() << endl;
}
Manager::print() const
{
Employee::print();
cout << level << endl;
}
int main ()
{
Employee e;
Manager m;
e.print();
m.print();
e=m;
e.print();
}
Class Exercise -
There are times when multiple programs or processes need to write to the same file. For example, when I include debug in a parallel program, all debug output will be written to the screen. It is useful to have each line of output identified with an indication of the particular program that spawned it.
Derive a class astring from the string class with one member function, a constructor that takes a char * and uses it to initialize the string class. Overload the << operator such that it precedes any output of an astring with [x] for an integer x. You may assume that the function int mypid() exists to provide the value of x.
Assuming mypid() returns 1 for the program below:
#include <iostream.h>
#include "astring.h"
int main()
{
astring hello("Hello world");
cout << hello << endl;
return 0;
}
The output will be
[1] Hello world