
    A basic tt(Fork) class should hide all bookkeeping details of a system
call like tt(fork) from its users. The class tt(Fork) developed here does
just that. The class itself only ensures the proper execution of the tt(fork)
system call. Normally, tt(fork) is called to start a child process, usually
boiling down to the execution of a separate process. This child process may
expect input at its standard input stream and/or may generate output to its
standard output and/or standard error streams. tt(Fork) does not know all
this, and does not have to know what the child process will do. tt(Fork)
objects should be able to start their child processes.

    tt(Fork)'s constructor cannot know what actions its child
process should perform. Similarly, it cannot know what actions the parent
process should perform. For these kind of  situations, the
        emi(template method design pattern)
        hi(design pattern: template method)
    was developed. According to Gamma c.s., the em(template method design
pattern)
    quote(
    ``Define(s) the skeleton of an algorithm in an operation, deferring some
    steps to subclasses. [The] Template Method (design pattern) lets
    subclasses redefine certain steps of an algorithm, without changing
    the algorithm's structure.''
    )

    This design pattern allows us to define an emi(abstract base class)
        hi(base class)
    already providing the essential steps related to the tt(fork) system call,
deferring the implementation of other parts of the tt(fork) system call to
subclasses.

    The tt(Fork) abstract base class has the following characteristics:
    itemization(
    it() It defines a data member tt(d_pid). In the parent process this data
member contains the child's emi(process id) and in the child process it has
the value 0. Its public interface declares only two members:
    itemization(
    it() a ti(fork) member function, responsible for the actual forking (i.e.,
        it creates the (new) child process);
    it() a tt(virtual) destructor tt(~Fork) (having an empty body).
    )
    Here is tt(Fork)'s interface:
            verbinclude(//CLASS examples/fork.h)
    it() All other non-virtual member functions are declared in the class's
tt(protected) section and can thus em(only) be used by derived classes. They
are:
        itemization(
        itt(pid()): The member function tt(pid) allows derived classes to
            access the system tt(fork)'s return value:
                verbinclude(//PID examples/fork.h)
        itt(waitForChild()): The member tt(int waitForChild) can be called by
            parent processes to wait for the completion of their child
            processes (as discussed below). This member is declared in the
            class interface. Its implementation is:
                verbinclude(-a examples/waitforchild.cc)
            This simple implementation returns the child's emi(exit status) to
            the parent. The called system function ti(waitpid) em(blocks)
            until the child terminates.
        )
    it() When tt(fork) system calls are used,
            em(parent processes) hi(parent process)
        and
            em(child processes) hi(child process)
        must always be distinguished. The main distinction between these
        processes is that tt(d_pid) becomes the child's process-id in the
        parent process, while tt(d_pid) becomes 0 in the child process
        itself. Since these two processes must always be distinguished (and
        present), their implementation by classes derived from tt(Fork) is
        enforced by tt(Fork)'s interface: the members tt(childProcess),
        defining the child process' actions and tt(parentProcess), defining
        the parent process' actions were defined as pure virtual functions.

    it() communication between parent- and child processes
        may use standard streams or other facilities, like em(pipes)
        (cf. section ref(PIPE)). To facilitate this inter-process
        communication, derived classes em(may) implement:
        itemization(
        itt(childRedirections()): this member should be overridden by derived
            classes if any standard stream (tt(cin, cout,)) or tt(cerr) must
            be redirected in the em(child) process (cf. section
            ref(REDIRECTION)). By default it has an empty implementation;
        itt(parentRedirections()): this member should be overridden by derived
            classes if any standard stream (tt(cin, cout,)) or tt(cerr) must
            be redirected in the em(parent) process. By default it has an
            empty implementation.
        )
    Redirection of the standard streams is necessary if parent and
child processes must communicate with each other via the standard streams.
Here are their default definitions. Since these functions are virtual
functions they should not be implemented inline, but in their own source file:
            verbinclude(//REDIRECT examples/forkvirtual.cc)
    )
