chap04.htm

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

HTM
405
字号
<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 4</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<B>C++ Tutorial - Chapter 4</B>

<P><B><FONT SIZE=+3>F</FONT><FONT SIZE=+2>UNCTIONS</FONT></B>

<P>This chapter discusses enhancements in the capabilities of functions
that have been made to C++. These changes make programming more convenient
and permit the compiler to do further checking for errors. A fair amount
of time is also spent in this chapter teaching the modern form of function
definition and prototyping.

<P>Prototyping allows the compiler to do additional type checking for your
function calls which can detect some programming errors. The first two
example programs in this chapter are designed to teach prototyping and
what it will do for you. Prototyping is a relatively new addition to C,
so even some experienced C programmers are not familiar with it. If you
have experience with prototyping you can skip directly to the section named
PASS BY REFERENCE later in this chapter.

<P><B>PROTOTYPES</B>

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

<P>Examine the file named PROTYPE1.CPP for our first look at a prototype
and an illustration of how it is used. The prototyping used in C++ is no
different than that used in ANSI-C. Actually, many C programmers take a
rather dim view of prototyping and seem reluctant to use it, but with C++
it is considerably more important and is in much heavier use. In fact,
prototyping is required to be used in some situations in C++.

<P>A prototype is a limited model of a more complete entity to come later.
In this case, the full function is the complete entity to come later and
the prototype is illustrated in line 4. The prototype gives a model of
the interface to the function that can be used to check the calls to the
function for the proper number of parameters and the correct types of parameters.
Each call to the function named <B>do_stuff()</B> must have exactly three
parameters or the compiler will issue an error message. In addition to
the correct number of parameters, the types must be compatible or the compiler
will issue an error message. Notice that when the compiler is working on
lines 12 and 13, the type checking can be done based on the prototype in
line 4 even though the function itself is not yet defined. If the prototype
is not given, the number of parameters will not be checked, nor will the
types of the parameters be checked. Without a prototype, if you have the
wrong number of parameters, you will get an apparently good compile and
link, but the program may do some very strange things when it is executed.

<P>To write the prototype, simply copy the header from the function to
the beginning of the program and append a semicolon to the end as a signal
to the compiler that this is not a function but a prototype. The variable
names given in the prototype are optional and act merely as comments to
the human reader since they are completely ignored by the compiler. You
could replace the variable name <B>wings </B>in line 4 with your first
name and there would be no difference in compilation. Of course, the next
person that had to read your program would be somewhat baffled with your
choice of variable names.

<P>In this case, the two function calls to this function, given in lines
12 and 13, are correct so no error will be listed during compilation.

<P>Even though we wish to use the <B>char </B>type for <B>eyes </B>in the
function, we wish to use it as a number rather than as a character. The
cast to <B>int </B>in line 22 is required to force the printout of the
numerical value rather than an ASCII character. The next example program
is similar but omits the cast to <B>int </B>in order to illustrate the
difference.

<P><B>COMPATIBLE TYPES</B>

<P>We mentioned compatible types earlier so we should review them just
a bit in order to make our discussion of prototyping complete. Compatible
types are any simple types that can be converted from one to another in
a meaningful way. For example, if you used an integer as the actual parameter
and the function was expecting a <B>float </B>type as the formal parameter,
the system would do the conversion automatically, without mentioning it
to you. This is also true of a <B>float </B>changing to a <B>char</B>,
or a <B>char </B>changing to an <B>int</B>. There are definite conversion
rules which would be followed. These rules are given in great detail in
section 3.2 of the ANSI-C standard and are also given on page 198 of the
second edition of the K&amp;R reference.

<P>If we supplied a pointer to an integer as the actual parameter and expected
an integer as the formal parameter in the function, the conversion would
not be made because they are two entirely different kinds of values. Likewise,
a structure would not be converted automatically to a <B>long float</B>,
an array, or even to a different kind of structure, because they are all
incompatible and cannot be converted in any meaningful manner. The entire
issue of type compatibility as discussed in chapter 2 of this tutorial
applies equally well to the compatibility of types when calling a function.
Likewise, the type specified as the return type, in this case <B>void</B>,
must be compatible with the expected return type in the calling statement,
or the compiler will issue a warning.

<P><B>HOW DOES PROTOTYPING WORK?</B>

<P>This is your chance to try prototyping for yourself and see how well
it works and what kinds of error messages you get when you do certain wrong
things. Change the actual parameters in line 12 to read (12.2, 13, 12345)
and see what the compiler says about that change. It will probably say
nothing because they are all type compatible. If you change it to read
(12.0, 13), it will issue a warning or error because there are not enough
arguments given. Likewise you should receive an error message if you change
one of the parameters in line 13 to an address by putting an ampersand
in front of one of the variable names. Finally, change the first word in
line 4 from <B>void </B>to <B>int </B>and see what kind of error message
is given. You will first be required to make the function header in line
18 agree with the prototype, then you will find that there is no value
returned from the function. You should have a good feeling that prototyping
is doing something worthwhile for you after making these changes.

<P>Be sure to compile and execute this program then make the changes recommended
above, attempting to compile it after each change.

<P><B>A LITTLE MORE PROTOTYPING</B>

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

<P>Examine the next example program named PROTYPE2.CPP for a little more
information on prototyping. This program is identical to the last one except
for a few small changes. The variable names have been omitted from the
prototype in line 4 as an illustration that they are interpreted only as
comments by the C++ compiler. The function header is formatted differently
to allow for a comment alongside each of the actual parameters. This should
make the function header a little more self explanatory. However, you should
remember that comments should not be used to replace careful selection
of variable names. In this particular case, the comments add essentially
nothing to the clarity of the program.

<P><B>WHAT DOES PROTOTYPING COST?</B>

<P>Prototyping is essentially free because it costs absolutely nothing
concerning the run time size or speed of execution. Prototyping is a compile
time check only, and slows down the compile time a negligible amount because
of the extra checking that the compiler must do. If prototyping finds one
error for you that you would have had to find with a debugger, it has more
than paid for itself for use in an entire project. I once spent 12 hours
of debugging time to find that I forgot to pass the address of a variable
to a function. Prototyping would have found the error on the first compilation
of that 2000 line program.

<P>The only price you pay to use prototyping is the extra size of the source
files because of the prototypes, and the extra time for the compiler to
read the prototypes during the compilation process, but both costs are
negligible.

<P>Be sure to compile and execute this example program. You will find that
it is identical to the last example program, except for the changes in
the prototype and the removal of the cast from the last line of the function.

<P><B>PASS BY REFERENCE</B>

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

<P>Examine the program named PASSREF.CPP for an example of a pass by reference,
a construct which is not available in ANSI-C. The reference variable was
mentioned in chapter 1 and it was recommended there that you don't use
it in the manner illustrated there. This example program illustrates a
situation where it can be used to your advantage. The pass by reference
allows the passing of a variable to a function and returning the changes
made in the function to the main program. In ANSI-C the same effect can
be seen when a pointer to a variable is passed to a function, but use of
a reference variable is a little cleaner.

<P>Observe the prototype in line 4 where the second variable has an ampersand
in front of the variable name. The ampersand instructs the compiler to
treat this variable as a reference to the actual variable passed from the
calling function. It acts like the actual variable from the main program
is used in the function. In the function itself, in lines 24 through 27,
the variable <B>in2 </B>is used just like any other variable but it acts
like we are using the variable passed to this function from the main program
not a copy of it. The other variable named <B>in1 </B>is treated just like
any other normal variable in ANSI-C. The name <B>in2 </B>is a synonym for
the variable named <B>index </B>in the main program, but the name <B>in1
</B>refers to a copy of the variable <B>count </B>from the main program.
In actual practice, a pointer is passed to the function and it is automatically
dereferenced when used in the function. This is transparent to you, the
programmer.

<P>If you prefer to omit the variable names in the prototypes, you would
write the prototype as follows;
<PRE>&nbsp;&nbsp;&nbsp; void fiddle(int, int&amp;);</PRE>
If you are a Pascal programmer, you will recognize that the variable named
<B>in1 </B>is treated just like a normal parameter in a Pascal call, a
call by value. The variable named <B>in2 </B>however, is treated like a
variable with the reserved word VAR used in front of it, usually referred
to as a call by reference. As mentioned earlier, the reference variable
used in C++ is actually a self dereferencing pointer which refers to, or
points to, the original value.

<P>When you compile and execute this program, you will find that the first
variable got changed in the function but the change was not reflected in
the original value when we returned to the main program. The second variable
however, was changed in the function and the new value was reflected back
into the variable in the main program which we can see when the values
are listed on the monitor. It should be clear that the reference allows
you to pass a parameter by reference to a function. After you gain experience
with the reference, you will use it to improve efficiency of some programs.

⌨️ 快捷键说明

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