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

📄 chapter07.html

📁 《C++编程思想》中文版。。。。。。。。。。。。。
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIC2Vone.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/27/2001
Translation Time:05:25:34
Translation Platform:Win32
Number of Output files:22
This File:Chapter07.html
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>7: Function Overloading &amp; Default Arguments</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview-head.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana" size = "-1">
    [ <a href="README-HTML.txt">Viewing Hints</a> ]
    [ <a href="http://www.mindview.net/CPPServices/SolutionGuide.html">Exercise Solutions</a> ]
    [ <a href="http://www.mindview.net/ThinkingInCPP2e.html">Volume 2</a> ]
    [ <a href="http://www.mindview.net/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/CPPServices/#PublicSeminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CPPServices/#SeminarsOnCD">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/CPPServices/#ConsultingServices">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana">
  Thinking in C++, 2nd ed. Volume 1</FONT></H2></FONT>
  <H3><FONT FACE="Verdana">&copy;2000 by Bruce Eckel</FONT></H3></FONT>
  
    <FONT FACE="Verdana" size = "-1">
     [ <a href="Chapter06.html">Previous Chapter</a> ] 
    [ <a href="Contents.html">Table of Contents</a> ] 
    [ <a href="DocIndex.html">Index</a> ]
     [ <a href="Chapter08.html">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc472654865"></A><A NAME="Heading236"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
7: Function Overloading &amp; Default Arguments</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>One of the important features in
any programming language is the convenient use of names. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index1378"></A><A NAME="Index1379"></A><A NAME="Index1380"></A><A NAME="Index1381"></A><FONT FACE="Georgia">When
you create an object (a variable), you give a name to a region of storage. A
function is a name for an action. By making up names to describe the system at
hand, you create a program that is easier for people to understand and change.
It&#8217;s a lot like writing prose &#8211; the goal is to communicate with your
readers.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A problem arises when mapping the concept
of nuance <A NAME="Index1382"></A>in human language onto a programming language.
Often, the same word expresses a number of different meanings, depending on
context. That is, a single word has multiple meanings &#8211; it&#8217;s
<I>overloaded</I>. This is very useful, especially when it comes to trivial
differences. You say &#8220;wash the shirt, wash the car.&#8221; It would be
silly to be forced to say, &#8220;shirt_wash the shirt, car_wash the car&#8221;
just so the listener doesn&#8217;t have to make any distinction about the action
performed. Human languages have built-in redundancy, so even if you miss a few
words, you can still determine the meaning. We don&#8217;t need unique
identifiers &#8211; we can deduce meaning from
context<A NAME="Index1383"></A>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Most programming languages, however,
require that you have a <A NAME="Index1384"></A><A NAME="Index1385"></A>unique
identifier for each function. If you have three different types of data that you
want to print: <B>int</B>, <B>char</B>, and <B>float</B>, you generally have to
create three different function names, for example, <B>print_int(&#160;)</B>,
<B>print_char(&#160;)</B>, and <B>print_float(&#160;)</B>. This loads extra work
on you as you write the program, and on readers as they try to understand
it.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In C++, another factor forces the
overloading of function names: the constructor<A NAME="Index1386"></A>. Because
the constructor&#8217;s name is predetermined by the name of the class, it would
seem that there can be only one constructor. But what if you want to create an
object in more than one way? For example, suppose you build a class that can
initialize itself in a standard way and also by reading information from a file.
You need two constructors, one that takes no arguments (the default constructor)
and one that takes a <B>string</B> as an argument, which is the name of the file
to initialize the object. Both are constructors, so they must have the same
name: the name of the class. Thus, function overloading is essential to allow
the same function name &#8211; the constructor in this case &#8211; to be used
with different argument types.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Although function overloading is a must
for constructors, it&#8217;s a general convenience and can be used with any
function, not just class member functions. In addition, function overloading
means that if you have two libraries that contain functions of the same name,
they won&#8217;t conflict as long as the argument lists are different.
We&#8217;ll look at all these factors in detail throughout this
chapter.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The theme of this chapter is convenient
use of function names. Function overloading allows you to use the same name for
different functions, but there&#8217;s a second way to make calling a function
more convenient. What if you&#8217;d like to call the same function in different
ways? When functions have long argument lists, it can become tedious to write
(and confusing to read) the function calls when most of the arguments are the
same for all the calls. A commonly used feature in C++ is called <I>default
arguments<A NAME="Index1387"></A><A NAME="Index1388"></A></I>. A default
argument is one the compiler inserts if it isn&#8217;t specified in the function
call. Thus, the calls <B>f(&#8220;hello&#8221;)</B>, <B>f(&#8220;hi&#8221;,
1)</B>, and <B>f(&#8220;howdy&#8221;, 2, &#8216;c&#8217;)</B> can all be calls
to the same function. They could also be calls to three overloaded functions,
but when the argument lists are this similar, you&#8217;ll usually want similar
behavior, which calls for a single function.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Function overloading and default
arguments really aren&#8217;t very complicated. By the time you reach the end of
this chapter, you&#8217;ll understand when to use them and the underlying
mechanisms that implement them during compiling and
linking.</FONT><A NAME="_Toc312373865"></A><A NAME="_Toc472654866"></A><BR></P></DIV>
<A NAME="Heading237"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
More name decoration</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In Chapter 4, the concept of
<A NAME="Index1389"></A><A NAME="Index1390"></A><I>name decoration</I>
<A NAME="Index1391"></A><A NAME="Index1392"></A>was introduced. In the
code</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>void</font> f();
<font color=#0000ff>class</font> X { <font color=#0000ff>void</font> f(); };</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">the function <B>f(&#160;)</B> inside the
scope of <B>class X</B> does not clash with the global version of
<B>f(&#160;)</B>. The compiler performs this scoping by manufacturing different
internal names for the global version of <B>f(&#160;)</B> and
<B>X::f(&#160;)</B>. In Chapter 4, it was suggested that the names are simply
the class name &#8220;decorated&#8221; together with the function name, so the
internal names the compiler uses might be <B>_f</B> and <B>_X_f</B>. However, it
turns out that function name decoration involves more than the class
name.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here&#8217;s why. Suppose you want to
overload two function names</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>void</font> print(<font color=#0000ff>char</font>);
<font color=#0000ff>void</font> print(<font color=#0000ff>float</font>);</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It doesn&#8217;t matter whether they are
both inside a class or at the global scope. The compiler can&#8217;t generate
unique internal identifiers if it uses only the scope of the function names.
You&#8217;d end up with <B>_print</B> in both cases. The idea of an overloaded
function is that you use the same function name, but different argument lists.
Thus, for overloading to work the compiler must decorate the function name with
the names of the argument <A NAME="Index1393"></A>types. The functions above,
defined at global scope, produce internal names that might look something like
<B>_print_char</B> and <B>_print_float</B>. It&#8217;s worth noting there is no
standard <A NAME="Index1394"></A>for the way names must be decorated by the
compiler, so you will see very different results from one compiler to another.
(You can see what it looks like by telling the compiler to generate
assembly-language output.) This, of course, causes problems if you want to buy
compiled libraries for a particular compiler and linker &#8211; but  even if
name decoration were standardized, there would be other roadblocks because of
the way different compilers generate
code<A NAME="Index1395"></A>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">That&#8217;s really all there is to
function overloading: you can use the same function name for different functions
as long as the argument lists are different. The compiler decorates the name,
the scope, and the argument lists to produce internal names for it and the
linker to
use.</FONT><A NAME="_Toc312373866"></A><A NAME="_Toc472654867"></A><BR></P></DIV>
<A NAME="Heading238"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Overloading on return values</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;s common to wonder, &#8220;Why
just scopes and argument lists? Why not return values?&#8221; It seems at first
that it would make sense to also decorate the return value with the internal
function name. Then you could overload on return
values<A NAME="Index1396"></A><A NAME="Index1397"></A>, as
well:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>void</font> f();
<font color=#0000ff>int</font> f();</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This works fine when the compiler can
unequivocally determine the meaning from the context, as in <B>int x =
f(&#160;);</B>. However, in C you&#8217;ve always been able to call a
<A NAME="Index1398"></A>function and ignore the return value (that is, you can
call the function for its <I>side effects</I>). How can the compiler distinguish
which call is meant in this case? Possibly worse is the difficulty the reader
has in knowing which function call is meant. Overloading solely on return value
is a bit too subtle, and thus isn&#8217;t allowed in
C++.</FONT><A NAME="_Toc312373867"></A><A NAME="_Toc472654868"></A><BR></P></DIV>
<A NAME="Heading239"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Type-safe linkage<BR><A NAME="Index1399"></A><A NAME="Index1400"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There is an added benefit to all of this
name decoration. A particularly sticky problem in C occurs when the client
programmer misdeclares a
<A NAME="Index1401"></A><A NAME="Index1402"></A>function, or, worse, a function
is called without declaring it first, and the compiler infers the function
declaration from the way it is called. Sometimes this function declaration is
correct, but when it isn&#8217;t, it can be a difficult bug to
find.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because all functions <I>must</I> be
declared before they are used in C++, the opportunity for this problem to pop up
is greatly diminished. The C++ compiler refuses to declare a function
automatically for you, so it&#8217;s likely that you will include the
appropriate header file. However, if for some reason you still manage to
misdeclare a function, either by declaring by hand or including the wrong header
file (perhaps one that is out of date), the name decoration provides a safety
net that is often referred to as <I>type-safe linkage</I>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Consider the following scenario. In one
file is the definition for a function:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C07:Def.cpp {O}</font>
<font color=#009900>// Function definition</font>
<font color=#0000ff>void</font> f(<font color=#0000ff>int</font>) {}
<font color=#009900>///:~ </font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the second file, the function is
misdeclared and then called:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C07:Use.cpp</font>
<font color=#009900>//{L} Def</font>
<font color=#009900>// Function misdeclaration</font>
<font color=#0000ff>void</font> f(<font color=#0000ff>char</font>);

<font color=#0000ff>int</font> main() {
<font color=#009900>//!  f(1); // Causes a linker error</font>
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Even though you can see that the function
is actually <B>f(int)</B>, the compiler doesn&#8217;t know this because it was
told &#8211; through an explicit declaration &#8211; that the function is
<B>f(char)</B>. Thus, the compilation is successful. In
<A NAME="Index1403"></A>C, the linker would also be successful, but <I>not</I>
in C++. Because the compiler decorates the names, the definition becomes
something like <B>f_int</B>, whereas the use of the function is <B>f_char</B>.
When the linker tries to resolve the reference to <B>f_char</B>, it can only
find <B>f_int</B>, and it gives you an error message. This is type-safe linkage.
Although the problem doesn&#8217;t occur all that often, when it does it can be
incredibly difficult to find, especially in a large project. This is one of the
cases where you can easily find a difficult error in a C program simply by
running it through the <A NAME="Index1404"></A>C++
compiler.</FONT><A NAME="_Toc312373868"></A><A NAME="_Toc472654869"></A><BR></P></DIV>
<A NAME="Heading240"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">

⌨️ 快捷键说明

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