In this lecture, we consider another kind of derivation, called a
private derivation. (There is also a protected derivation, but we won't
discuss it in detail.) As an example of private derivation, we will define
a class called Package that is derived from our box class. Intuitively,
think of a package as a cardboard box. We will allow a package to be
placed inside another package using a member function called Store. If a
package is stored inside another package, then the package inside must be
smaller than the package outside. (This we can determine using the compare
function.) The important part is that once we place a package inside
another one, we do not want the package inside to grow or the package
outside to shrink. Otherwise, the condition that packages are only stored
inside larger packages is no longer true. Thus, we want to make sure that
the member functions grow() and shrink() are not
accessible through a package object. This can be achieved using a private
derivation.
Another way to think about this. In Lecture 16 we wanted to think of Cubes and
ColorCubes as Boxes. Anything we can do to a Box we allow to be done to a
Cube and to a ColorCube. So, a Cube is a kind of Box; a ColorCube is a kind
of Cube and a kind of Box. When classes follow this "is a kind of"
relationship, we generally use a public derivation. In the Package example,
we don't want to consider a Package a kind of Box, so we use a private
derivation.
In the header file for the Package
class, we declare the Package class to be a private derivation of the Box
class in the following line, using the keyword "private".
class Package : private Box { // private derivation of class Box
The rest of the declaration includes two constructors and the public member
functions identify(), Store(), empty() and
content(). These are the only publicly accessible members of
Package. Even though Package inherits all the members of Box, the public
members (e.g. grow() and shrink()) are not accessible
through a Package object. This has the intended effect.
Other notable points about the package implementation:
- The main program and sample run show how the Package
class is used.
- A second main program and sample run show that the compiler
generates an error if you try to access the grow() function
through a Package object.
- The Store() function uses the compare() function to
determine whether a package fits inside another package. In order to do so,
the Store() function needs some mechanism to refer to the host
object. (When we call p2.Store(&p1) in the main program,
p2 is the host object for this particular call.) This is
accomplished using the this pointer. Each member function has a
local variable this which points to the host object. Thus the
function call r = compare(*this, *item) ; has the intended
effect of comparing the host object with the package given in as a
parameter.