⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap06.htm

📁 Since the field of object oriented programming is probably new to you, you will find that there is a
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="Gordon Dodrill">
   <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (Win95; I) [Netscape]">
   <TITLE>C++ Tutorial - Chapter 6</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<B>C++ Tutorial - Chapter 6</B>

<P><B><FONT SIZE=+3>M</FONT><FONT SIZE=+2>ORE</FONT><FONT SIZE=+3> E</FONT><FONT SIZE=+2>NCAPSULATION</FONT></B>

<P><B>WHY BOTHER WITH ENCAPSULATION?</B>

<P>We asked this question earlier, but now that we have a little experience,
we can provide a much better answer. Encapsulation protects data from accidental
corruption, and constructors guarantee proper initialization. Both prevent
errors that we are very prone to make since we are thinking only about
the internals of the class when we are writing it. Later, when we are actually
using the class, we have no need to concern ourselves with the internal
structure or operation, but can spend our energies using the class to solve
the overall problem we are working on. As you may guess, there is a lot
more to learn about the use and benefits of classes so we will dive right
into some new topics.

<P>The purpose of this chapter is to illustrate how to use some of the
traditional aspects of C or C++ with classes and objects. Pointers to an
object as well as pointers within an object will be illustrated. Arrays
embedded within an object, and an array of objects will be illustrated.
Since objects are simply another C++ data construct, all of these things
are possible and can be used if needed.

<P>In order to have a systematic study, we will use the program named BOXES1.CPP
from the last chapter as a starting point and we will add a few new constructs
to it for each example program. You will recall that it was a very simple
program with the class definition, the class implementation, and the main
program all in one file. This was selected as a starting point because
we will eventually make changes to all parts of the program and it will
be convenient to have it all in a single file for illustrative purposes.
It must be kept in mind however that the proper way to use these constructs
is to separate them into the three files as was illustrated in BOX.H, BOX.CPP,
and BOXES2.CPP in the last chapter. This allows the implementor of <B>box
</B>to supply the user with only the interface, namely BOX.H. Not giving
him the implementation file named BOX.CPP, is practicing the technique
of information hiding. As we have said many times, it seems silly to break
up such a small program into three separate files, and it is sort of silly.
The last chapter of this tutorial will illustrate a program large enough
to require dividing the program up into many separate files.

<P><B>AN ARRAY OF OBJECTS</B>

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

<P>Examine the file named OBJARRAY.CPP for our first example of an array
of objects. This file is nearly identical to the file named BOX1.CPP until
we come to line 45 where an array of 4 boxes are defined.

<P>Recalling the operation of the constructor you will remember that each
of the four <B>box </B>objects will be initialized to the values defined
within the constructor since the constructor will be executed for each
<B>box </B>as they are defined. In order to define an array of objects,
a constructor for that object with no parameters must be available. (We
have not yet illustrated a constructor with initializing parameters, but
we will in the next program.) This is an efficiency consideration since
it would probably be an error to initialize all elements of an array of
objects to the same value. We will see the results of executing the constructor
when we compile and execute the file later.

<P>Line 50 defines a <B>for </B>loop that begins with 1 instead of the
normal starting index for an array leaving the first object, named <B>group[0],</B>
to use the default values stored when the constructor was called. You will
observe that sending a message to one of the objects uses the same construct
as is used for any object. The name of the array followed by its index
in square brackets is used to send a message to one of the objects in the
array. This is illustrated in line 51 and the operation of that code should
be clear to you. The other method is called in the output statement in
lines 58 and 59 where the area of the four boxes in the <B>group </B>array
are listed on the monitor.

<P>Another fine point should be mentioned. The integer variable named <B>index
</B>is defined in line 50 and is still available for use in line 57 since
we have not yet left the enclosing block which begins in line 44 and extends
to line 68. But this is true only if your compiler is aging slightly. If
you have a new compiler, you may find that <B>index </B>is undefined in
line 57. See the discussion in Chapter 1 if this is not clear.

<P><B>DECLARATION AND DEFINITION OF A VARIABLE</B>

<P>An extra variable was included for illustration, the one named <B>extra_data</B>
in line seven. Since the keyword <B>static </B>is used to modify this variable
in line 8, it is an external variable and only one copy of this variable
will ever exist. All seven objects of this class share a single copy of
this variable which is global to the objects defined in line 44.

<P>The variable is actually only declared here which says it will exist
somewhere, but it is not yet defined. A declaration says the variable will
exist and gives it a name, but the definition actually defines a place
to store it somewhere in the computers memory space. By definition, a static
variable can be declared in a class header but it cannot be defined there,
so it is usually defined in the implementation file. In this case it is
defined in line 17 and can then be used throughout the class.

<P>Figure 6-1 is a graphical representation of some of the variables. Note
that the objects named <B>large</B>, <B>group[0]</B>, <B>group[1]</B>,
and <B>group[2]</B> are not shown but they also share the variable named
<B>extra_data</B>. They are not shown in order to simplify the picture
and enhance the clarity. Each object has its own personal <B>length </B>and
<B>width </B>because they are not declared <B>static</B>.

<P><IMG SRC="CPP0601.GIF" VSPACE=20 BORDER=0 HEIGHT=341 WIDTH=520>

<P>Line 24 of the constructor sets the single global variable to 1 each
time an object is declared. Only one assignment is necessary so the other
six are actually wasted code. It is generally not a good idea to assign
a value to a <B>static </B>member in a constructor, but in this case, it
illustrates how the static variable works. To illustrate that there is
only one variable shared by all objects of this class, the method to read
its value also increments it. Each time it is read in lines 61 through
65, it is incremented and the result of the execution proves that there
is only a single variable shared by all objects of this class. You will
also note that the method named <B>get_extra()</B> is defined within the
class declaration so it will be assembled into the final program as inline
code.

<P>You will recall the 2 static variables we declared in lines 18 and 19
of DATE.H in chapter 5 of this tutorial. We defined them in lines 9 and
10 of DATE.CPP and overlooked a complete explanation of what they did at
that time. The declaration and definition of these variables should be
considered a good example of the proper place to put these constructs in
your classes.

<P>Be sure you understand this program and especially the static variable,
then compile and execute it to see if you get the same result as listed
at the end of the program.

<P><B>A STRING WITHIN AN OBJECT</B>

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

<P>Examine the program named OBJSTRNG.CPP for our first example of an object
with an embedded string. Actually, the object does not have an embedded
string, it has an embedded pointer, but the two work so closely together
that we can study one and understand both.

<P>You will notice that line 8 contains a pointer to a <B>char </B>named
<B>line_of_text</B>. The constructor contains an input parameter which
is a pointer to a string which will be copied to the string named <B>line_of_text</B>
within the constructor. We could have defined the variable <B>line_of_text
</B>as an actual array in the class, then used <B>strcpy()</B> to copy
the string into the object and everything would have worked the same, but
we will leave that as an exercise for you at the end of this chapter. It
should be pointed out that we are not limited to passing a single parameter
to a constructor. Any number of parameters can be passed, as will be illustrated
later.

<P>You will notice that when the three boxes are defined this time, we
supply a string constant as an actual parameter with each declaration which
is used by the constructor to assign the string pointer some data to point
to. When we call <B>get_area() </B>in lines 50 through 54, we get the message
displayed and the area returned. It would be prudent to put these operations
in separate methods since there is no apparent connection between printing
the message and calculating the area, but it was written this way to illustrate
that it can be done. What this really says is that it is possible to have
a method that has a side effect, the message output to the monitor, and
a return value, the area of the box. However, as we discussed in chapter
4 when we studied DEFAULT.CPP, the order of evaluation is sort of funny,
so we broke each line into two lines.

<P>After you understand this program, compile and execute it.

<P><B>AN OBJECT WITH AN INTERNAL POINTER</B>

<P>Example programs ------> <B><A HREF="OBJINTPT.CPP">OBJINTPT.CPP</A></B>

<P>The program named OBJINTPT.CPP is our first example program with an
embedded pointer which will be used for dynamic allocation of data.

<P>In line 8 we declare a pointer to an integer variable, but it is only
a pointer, there is no storage associated with it. The constructor therefore
allocates an integer type variable on the heap for use with this pointer
in line 22. It should be clear to you that the three objects defined in
line 46 each contain a pointer which points into the heap to three different
locations. Each object has its own dynamically allocated variable for its
own private use. Moreover each has a value of 112 stored in its dynamically
allocated data because line 23 stores that value in each of the three locations,
once for each call to the constructor.

<P>In such a small program, there is no chance that we will exhaust the
heap, so no test is made for unavailable memory. In a real production program,
it would be mandatory to test that the value of the returned pointer is
not NULL to assure that the data actually did get allocated.

<P>The method named <B>set()</B> has three parameters associated with it
and the third parameter is used to set the value of the new dynamically
allocated variable. There are two messages passed, one to the small box
and one to the large box. As before, the medium box is left with its default
values.

<P>The three areas are displayed followed by the three stored values in
the dynamically allocated variables, and we finally have a program that
requires a destructor in order to be completely proper. If we simply leave
the scope of the objects as we do when we leave the <B>main()</B> program,
we will leave the three dynamically allocated variables on the heap with
nothing pointing to them. They will be inaccessible and will therefore
represent wasted storage on the heap. For that reason, the destructor is
used to <B>delete </B>the variable which the pointer named <B>point </B>is
referencing, as each object goes out of existence. In this case, lines
38 and 39 assign zero to variables that will be automatically deleted.
Even though these lines of code really do no good, they are legal statements.

<P>Actually, in this particular case, the variables will be automatically
reclaimed when we return to the operating system because all program cleanup
is done for us at that time. This is an illustration of good programming
practice, that of cleaning up after yourself when you no longer need some
dynamically allocated variables.

<P>One other construct should be mentioned again, that of the inline method
implementations in line 12 and 13. As we mentioned in chapter 5, inline
functions can be used where speed is of the utmost in importance since
the code is assembled inline rather than by actually making a method call.
Since the code is defined as part of the declaration, the system will assemble
it inline, and a separate implementation for these methods is not needed.
If the inline code is too involved, the compiler is allowed to ignore the
inline request and will actually assemble it as a separate method, but
it will do it invisibly to you and will probably not even tell you about
it.

<P>Remember that we are interested in using information hiding and inline
code prevents hiding of the implementation, putting it out in full view.
Many times you will be more interested in speeding up a program than you
are in hiding a trivial implementation. Since most inline methods are trivial,
you should feel free to use the inline code construct wherever it is expedient.
Be sure to compile and execute this program.

<P><B>A DYNAMICALLY ALLOCATED OBJECT</B>

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

<P>Examine the file named OBJDYNAM.CPP for our first look at a dynamically
allocated object. This is not any different than any other dynamically
allocated object, but an example is always helpful.

<P>In line 40 we define a pointer to an object of type <B>box </B>and since
it is only a pointer with nothing to point to, we dynamically allocate
an object for it in line 45, with the object being created on the heap
just like any other dynamically allocated variable. When the object is
created in line 45, the constructor is called automatically to assign values
to the two internal storage variables. Note that the constructor is not
called when the pointer is defined since there is nothing to initialize.
It is called when the object is allocated.

<P>Reference to the components of the object are handled in much the same
way that structure references are made, through use of the pointer operator
as illustrated in lines 51 through 53. Of course you can use the pointer
dereferencing method without the arrow such as (*point).set(12, 12); as
a replacement for line 52 but the arrow notation is much more universal
and should be used. Finally, the object is deleted in line 55 and the program
terminates. If there were a destructor for this class, it would be called
automatically as part of the <B>delete </B>statement to clean up the object
prior to deletion.

<P>You have probably noticed by this time that the use of objects is not
much different from the use of structures. Be sure to compile and execute
this program after you have studied it thoroughly.

<P><B>AN OBJECT WITH A POINTER TO ANOTHER OBJECT</B>

⌨️ 快捷键说明

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