chap06.htm

来自「Since the field of object oriented progr」· HTM 代码 · 共 801 行 · 第 1/3 页

HTM
801
字号
<P>Example program ------> <B><A HREF="OBJLIST.CPP">OBJLIST.CPP</A></B>

<P>The program named OBJLIST.CPP contains an object with an internal reference
to another object of its own class. This is the standard structure used
for a singly linked list and we will keep the use of it very simple in
this program.

<P>The constructor contains the statement in line 22 which assigns the
pointer the value of NULL to initialize the pointer. This is a good idea
for all of your programming, don't allow any pointer to point off into
space, but initialize all pointers to something. By assigning the pointer
within the constructor, you guarantee that every object of this class will
automatically have its pointer initialized. It will be impossible to overlook
the assignment of one of these pointers.

<P>Two additional methods are declared in lines 13 and 14 with the one
in line 14 having a construct we have not yet mentioned in this tutorial.
This method returns a pointer to an object of the <B>box </B>class. As
you are aware, you can return a pointer to a <B>struct </B>in standard
C, and this is a parallel construct in C++. The implementation in lines
49 through 52 returns the pointer stored as a member variable within the
object. We will see how this is used when we get to the actual program.

<P><IMG SRC="CPP0602.GIF" HSPACE=20 VSPACE=20 BORDER=0 HEIGHT=342 WIDTH=434>

<P>An extra pointer named <B>box_pointer</B> is defined in the main program
for use later and in line 67 we make the embedded pointer within the <B>small
box</B> point to the <B>medium box</B>. Line 68 makes the embedded pointer
within the <B>medium box</B> point to the <B>large box.</B> We have effectively
generated a linked list with three elements. In line 70 we make the extra
pointer point to the <B>small box</B>. Continuing in line 71 we use it
to refer to the <B>small box</B> and update it to the value contained in
the <B>small box</B> which is the address of the <B>medium box</B>. We
have therefore traversed from one element of the list to another by sending
a message to one of the objects. If line 71 were repeated exactly as shown,
it would cause the extra pointer to refer to the <B>large box</B>, and
we would have traversed the entire linked list which is only composed of
three elements. Figure 6-2 is a graphical representation of the data space
following execution of line 70. Note that only a portion of each object
is actually depicted here to keep it simple.

<P><B>ANOTHER NEW KEYWORD this</B>

<P>Another new keyword is available in C++, the keyword <B>this</B>. The
word <B>this </B>is defined within any object as being a pointer to the
object in which it is contained. It is implicitly defined as;
<PRE>&nbsp;&nbsp;&nbsp; class_name *this;</PRE>
and is initialized to point to the object for which the member function
is invoked. This pointer is most useful when working with pointers and
especially with a linked list when you need to reference a pointer to the
object you are inserting into the list. The keyword <B>this </B>is available
for this purpose and can be used in any object. Actually the proper way
to refer to any variable within a list is through use of the predefined
pointer <B>this</B>, by writing <B>this->variable_name</B>, but the compiler
assumes the pointer is used, and we can simplify every reference by omitting
the pointer. Use of the keyword <B>this </B>is not illustrated in a program
at this point, but will be used in one of the larger example programs later
in this tutorial.

<P>You should study this program until you understand it completely then
compile and execute it in preparation for our next example program.

<P><B>A LINKED LIST OF OBJECTS</B>

<P>Example program ------> <B><A HREF="OBJLINK.CPP">OBJLINK.CPP</A></B>

<P>The next example program in this chapter is named OBJLINK.CPP and is
a complete example of a linked list written in object oriented notation.

<P>This program is very similar to the last one. In fact it is identical
until we get to the <B>main()</B> program. You will recall that in the
last program the only way we had to set or use the embedded pointer was
through use of the two methods named <B>point_at_next()</B> and <B>get_next()</B>
which are listed in lines 42 through 52 of the present program. We will
use these to build up our linked list then traverse and print the list.
Finally, we will <B>delete </B>the entire list to free the space on the
heap.

<P>In lines 57 through 59 we define three pointers for use in the program.
The pointer named <B>start </B>will always point to the beginning of the
list, but <B>temp </B>will move down through the list as we create it.
The pointer named <B>box_pointer</B> will be used for the creation of each
object. We execute the loop in lines 62 through 75 to generate the list
where line 64 dynamically allocates a new object of the <B>box class </B>and
line 65 fills it with nonsense data for illustration. If this is the first
element in the list, the <B>start </B>pointer is set to point to this element,
but if elements already exist, the <B>last </B>element in the list is assigned
to point to the new element. In either case, the <B>temp </B>pointer is
assigned to point to the last element of the list, in preparation for adding
another element if there is another element to be added.

<P>In line 78, the pointer named <B>temp </B>is caused to point to the
first element and it is used to increment its way through the list by updating
itself in line 82 during each pass through the loop. When <B>temp </B>has
the value of NULL, which it gets from the last element of the list, we
are finished traversing the list.

<P>Finally, we delete the entire list by starting at the beginning and
deleting one element each time we pass through the loop in lines 87 through
92.

<P>A careful study of the program will reveal that it does indeed generate
a linked list of ten elements, each element being an object of class <B>box</B>.
The length of this list is limited by the practicality of how large a list
we desire to print out, but it could be lengthened to many thousands of
these simple elements provided you have enough memory available to store
them all.

<P>Once again, the success of the dynamic allocation is not checked as
it should be in a correctly written program. Be sure to compile and execute
this example program.

<P><B>NESTING OBJECTS</B>

<P>Example program ------> <B><A HREF="NESTING.CPP">NESTING.CPP</A></B>

<P>Examine the program named NESTING.CPP for an example of nesting classes
which results in nested objects. A nested object could be illustrated with
your computer in a rather simple manner. The computer itself is composed
of many items which work together but work entirely differently, such as
a keyboard, a disk drive, and a power supply. The computer is composed
of these very dissimilar items and it is desirable to discuss the keyboard
separately from the disk drive because they are so different. A computer
class could be composed of several objects that are dissimilar by nesting
the dissimilar classes within the computer class.

<P>If however, we wished to discuss disk drives, we may wish to examine
the characteristics of disk drives in general, then examine the details
of a hard disk, and the differences of floppy disks. This would involve
inheritance because much of the data about both drives could be characterized
and applied to the generic disk drive then used to aid in the discussion
of the other three. We will study inheritance in the next three chapters,
but for now we will look at the embedded or nested class.

<P><IMG SRC="CPP0603.GIF" HSPACE=20 VSPACE=20 BORDER=0 HEIGHT=357 WIDTH=374>

<P>This example program contains a class named <B>box </B>which contains
an object of another class embedded within it in line 17, the <B>mail_info</B>
class. It is depicted graphically in figure 6-3. This object is available
for use only within the class implementation of <B>box </B>because that
is where it is defined. The <B>main()</B> program has objects of class
<B>box </B>defined but no objects of class <B>mail_info</B>, so the <B>mail_info</B>
class cannot be referred to in the <B>main()</B> program. In this case,
the <B>mail_info</B> class object is meant to be used internally to the
<B>box </B>class and one example is given in line 22 where a message is
sent to the <B>label.set() </B>method to initialize the variables. Additional
methods could be used as needed, but these are given as an illustration
of how they can be called.

<P>Of prime importance is the fact that there are never any objects of
the <B>mail_info</B> class declared directly in the <B>main() </B>program,
they are inherently declared when the enclosing objects of <B>class box</B>
are declared. Of course objects of the <B>mail_info</B> class could be
declared and used in the <B>main()</B> program if needed, but they are
not in this example program. In order to be complete, the <B>box </B>class
should have one or more methods to use the information stored in the object
of the <B>mail_info</B> class. Study this program until you understand
the new construct, then compile and execute it.

<P>If the class and the nested classes require parameter lists for their
respective constructors an initialization list can be given. This will
be discussed and illustrated later in this tutorial.

<P><B>OPERATOR OVERLOADING</B>

<P>Example program ------> <B><A HREF="OPOVERLD.CPP">OPOVERLD.CPP</A></B>

<P>The example file named OPOVERLD.CPP contains examples of overloading
operators. This allows you to define a class of objects and redefine the
use of the normal operators. The end result is that objects of the new
class can be used in as natural a manner as the predefined types. In fact,
they seem to be a part of the language rather than your own add-on.

<P>In this case we overload the + operator and the * operator, with the
declarations in lines 11 through 13, and the definitions in lines 17 through
41. The methods are declared as <B>friend </B>functions so we can use the
double parameter functions as listed. If we did not use the friend construct,
the function would be a part of one of the objects and that object would
be the object to which the message was sent. Including the <B>friend </B>construct
allows us to separate this method from the object and call the method with
infix notation. Using this technique, it can be written as <B>object1 +
object2</B> rather than <B>object1.operator+(object2)</B>. Also, without
the <B>friend </B>construct we could not use an overloading with an <B>int
</B>type variable for the first parameter because we can not send a message
to an integer type variable such as <B>int.operator+(object)</B>. Two of
the three operator overloadings use an <B>int </B>for the first parameter
so it is necessary to declare them as friend functions.

<P>There is no upper limit to the number of overloadings for any given
operator. Any number of overloadings can be used provided the parameters
are different for each particular overloading.

<P>The header in line 17 illustrates the first overloading where the +
operator is overloaded by giving the return type followed by the keyword
operator and the operator we wish to overload. The two formal parameters
and their types are then listed in the parentheses and the normal function
operations are given in the implementation of the function in lines 19
through 22. The observant student will notice that the implementation of
the <B>friend </B>functions are not actually a part of the class because
the class name is not prepended onto the method name in line 17. There
is nothing unusual about this implementation, it should be easily understood
by you at this point. For purposes of illustration, some silly mathematics
are performed in the method implementation, but any desired operations
can be done.

<P>The biggest difference occurs in line 57 where this method is called
by using the infix notation instead of the usual message sending format.
Since the variables <B>small </B>and <B>medium </B>are objects of the <B>box
</B>class, the system will search for a way to use the + operator on two
objects of class <B>box </B>and will find it in the overloaded <B>operator+</B>
method we have just discussed. The operations within the method implementation
can be anything we need them to be, and they are usually much more meaningful
than the silly math included here.

<P>In line 59 we ask the system to add an <B>int </B>type constant to an
object of class <B>box</B>, so the system finds the other overloading of
the + operator beginning in line 26 to perform this operation. Also in
line 61 we ask the system to use the * operator to do something to an <B>int
</B>constant and an object of class <B>box</B>, which it satisfies by finding
the method in lines 35 through 41. Note that it would be illegal to attempt
to use the * operator the other way around, namely <B>large * 4</B> since
we did not define a method to use the two types in that order. Another
overloading could be given with reversed types, and we could then use the
reverse order in a program.

<P>You will notice that when using operator overloading, we are also using
function name overloading since some of the function names are the same.

<P>When we use operator overloading in this manner, we actually make our
programs look like the class is a natural part of the language since it
is integrated into the language so well. C++ is therefore an extendible
language and can be molded to fit the mechanics of the problem at hand.

<P><B>OPERATOR OVERLOADING CAVEATS</B>

<P>Each new topic we study has its pitfalls which must be warned against
and the topic of operator overloading seems to have the record for pitfalls
since it is so prone to misuse and has several problems. The overloading
of operators is only available for classes, you cannot redefine the operators
for the predefined simple types. This would probably be very silly anyway
since the code could be very difficult to read if you changed some of them
around.

<P>The logical and "&amp;&amp;" and the logical or "||" operators can be
overloaded for the classes you define, but they will not operate as short
circuit operators. All members of the logical construction will be evaluated
with no regard concerning the outcome. Of course the normal predefined
logical operators will continue to operate as short circuit operators as
expected, but not the overloaded ones.

<P>If the increment "++" or decrement "--" operators are overloaded, the
system has no way of telling whether the operators are used as preincrement
or postincrement (or predecrement or postdecrement) operators. Which method
is used is implementation dependent, so you should use them in such a way
that it doesn't matter which is used.

<P>Be sure to compile and execute OPOVERLD.CPP before continuing on to
the next example program.

<P><B>FUNCTION OVERLOADING IN A CLASS</B>

<P>Example program ------><B> <A HREF="FUNCOVER.CPP">FUNCOVER.CPP</A></B>

<P>Examine the program named FUNCOVER.CPP for an example of function name
overloading within a class. In this program the constructor is overloaded
as well as one of the methods to illustrate what can be done.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?