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

📄 ch17.htm

📁 Why C++ is the emerging standard in software development. The steps to develop a C++ program. How
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<BLOCKQUOTE>	<P><HR><FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>It never hurts to use inclusion	guards. Often they will save you hours of debugging time. <HR></BLOCKQUOTE><H4 ALIGN="CENTER"><A NAME="Heading11"></A><FONT COLOR="#000077">Defining on theCommand Line</FONT></H4><P>Almost all C++ compilers will let you <TT>#define</TT> values either from thecommand line or from the integrated development environment (and usually both). Thusyou can leave out lines 1 and 2 from Listing 17.1, and define <TT>DemoVersion</TT>and <TT>BetaTestVersion</TT> from the command line for some compilations, and notfor others.</P><P>It is common to put in special debugging code surrounded by <TT>#ifdef DEBUG</TT>and <TT>#endif</TT>. This allows all the debugging code to be easily removed fromthe source code when you compile the final version; just don't define the term <TT>DEBUG</TT>.<H4 ALIGN="CENTER"><A NAME="Heading12"></A><FONT COLOR="#000077">Undefining</FONT></H4><P>If you have a name defined and you'd like to turn it off from within your code,you can use <TT>#undef</TT>. This works as the antidote to <TT>#define</TT>. Listing17.2 provides an illustration of its use.</P><P><A NAME="Heading13"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 17.2. Using#undef.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     #define DemoVersion2:     #define DOS_VERSION 53:     #include &lt;iostream.h&gt;4:5:6:     int main()7:     {8:9:     cout &lt;&lt; &quot;Checking on the definitions of DemoVersion, DOS_VERSION  &#194;                _and WINDOWS_VERSION...\n&quot;;10:11:    #ifdef DemoVersion12:       cout &lt;&lt; &quot;DemoVersion defined.\n&quot;;13:    #else14:       cout &lt;&lt; &quot;DemoVersion not defined.\n&quot;;15:    #endif16:17:    #ifndef DOS_VERSION18:       cout &lt;&lt; &quot;DOS_VERSION not defined!\n&quot;;19:    #else20:       cout &lt;&lt; &quot;DOS_VERSION defined as: &quot; &lt;&lt; DOS_VERSION &lt;&lt; endl;21:    #endif22:23:    #ifdef WINDOWS_VERSION24:       cout &lt;&lt; &quot;WINDOWS_VERSION defined!\n&quot;;25:    #else26:       cout &lt;&lt; &quot;WINDOWS_VERSION was not defined.\n&quot;;27:    #endif28:29:    #undef DOS_VERSION30:31:     #ifdef DemoVersion32:       cout &lt;&lt; &quot;DemoVersion defined.\n&quot;;33:    #else34:       cout &lt;&lt; &quot;DemoVersion not defined.\n&quot;;35:    #endif36:37:    #ifndef DOS_VERSION38:       cout &lt;&lt; &quot;DOS_VERSION not defined!\n&quot;;39:    #else40:       cout &lt;&lt; &quot;DOS_VERSION defined as: &quot; &lt;&lt; DOS_VERSION &lt;&lt; endl;41:    #endif42:43:    #if_Tz'WINDOWS_VERSION44:       cout &lt;&lt; &quot;WINDOWS_VERSION defined!\n&quot;;45:    #else46:       cout &lt;&lt; &quot;WINDOWS_VERSION was not defined.\n&quot;;47:    #endif48:49:     cout &lt;&lt; &quot;Done.\n&quot;;50:     return 0;<TT>51: }</TT></FONT><FONT COLOR="#0066FF">Output: Checking on the definitions of DemoVersion, DOS_VERSION &#194;                _and WINDOWS_VERSION...\n&quot;;DemoVersion defined.DOS_VERSION defined as: 5WINDOWS_VERSION was not defined.DemoVersion defined.DOS_VERSION not defined!WINDOWS_VERSION was not defined.Done.</FONT></PRE><DL>	<DD><FONT COLOR="#0066FF"></FONT></DL><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 17.2 is the sameas Listing 17.1 until line 29, when <TT>#undef DOS_VERSION</TT> is called. This removesthe definition of the term <TT>DOS_VERSION</TT> without changing the other definedterms (in this case, <TT>DemoVersion</TT>). The rest of the listing just repeatsthe printouts. The tests for <TT>DemoVersion</TT> and <TT>WINDOWS_VERSION</TT> actas they did the first time, but the test for <TT>DOS_VERSION</TT> now evaluates <TT>TRUE</TT>.In this second case <TT>DOS_VERSION</TT> does not exist as a defined term.<H4 ALIGN="CENTER"><A NAME="Heading15"></A><FONT COLOR="#000077">Conditional Compilation</FONT></H4><P>By combining <TT>#define</TT> or command-line definitions with <TT>#ifdef</TT>,<TT>#else</TT>, and <TT>#ifndef</TT>, you can write one program that compiles differentcode, depending on what is already <TT>#define</TT>d. This can be used to createone set of source code to compile on two different platforms, such as DOS and Windows.</P><P>Another common use of this technique is to conditionally compile in some codebased on whether <TT>debug</TT> has been defined, as you'll see in a few moments.<BLOCKQUOTE>	<P><HR><B>DO</B> use conditional compilation when you need to create more than one version	of your code at the same time. <B>DON'T</B> let your conditions get too complex to	manage. <B>DO</B> use <TT>#undef</TT> as often as possible to avoid leaving stray	definitions in your code. <B>DO</B> use inclusion guards! <HR></BLOCKQUOTE><H3 ALIGN="CENTER"><A NAME="Heading16"></A><FONT COLOR="#000077">Macro Functions</FONT></H3><P>The <TT>#define</TT> directive can also be used to create macro functions. A macrofunction is a symbol created using <TT>#define</TT> and that takes an argument, muchlike a function does. The preprocessor will substitute the substitution string forwhatever argument it is given. For example, you can define the macro <TT>TWICE</TT>as</P><PRE><FONT COLOR="#0066FF">#define TWICE(x) ( (x) * 2 )</FONT></PRE><P>and then in your code you write</P><PRE><FONT COLOR="#0066FF">TWICE(4)</FONT></PRE><P>The entire string <TT>TWICE(4)</TT> will be removed, and the value <TT>8</TT>will be substituted! When the precompiler sees the <TT>4</TT>, it will substitute<TT>( (4) * 2 )</TT>, which will then evaluate to <TT>4 * 2</TT> or <TT>8</TT>.</P><P>A macro can have more than one parameter, and each parameter can be used repeatedlyin the replacement text. Two common macros are <TT>MAX</TT> and <TT>MIN</TT>:</P><PRE><FONT COLOR="#0066FF">#define MAX(x,y) ( (x) &gt; (y) ? (x) : (y) )#define MIN(x,y) ( (x) &lt; (y) ? (x) : (y) )</FONT></PRE><P>Note that in a macro function definition, the opening parenthesis for the parameterlist must immediately follow the macro name, with no spaces. The preprocessor isnot as forgiving of white space as is the compiler.</P><P>If you were to write</P><PRE><FONT COLOR="#0066FF">#define MAX (x,y) ( (x) &gt; (y) ? (x) : (y) )</FONT></PRE><P>and then tried to use <TT>MAX</TT> like this,</P><PRE><FONT COLOR="#0066FF">int x = 5, y = 7, z;z = MAX(x,y);</FONT></PRE><P>the intermediate code would be</P><PRE><FONT COLOR="#0066FF">int x = 5, y = 7, z;z = (x,y) ( (x) &gt; (y) ? (x) : (y) ) (x,y)</FONT></PRE><P>A simple text substitution would be done, rather than invoking the macro function.Thus the token <TT>MAX</TT> would have substituted for it <TT>(x,y) ( (x) &gt; (y)? (x) : (y) )</TT>, and then that would be followed by the <TT>(x,y)</TT> which followed<TT>Max</TT>.</P><P>By removing the space between <TT>MAX</TT> and <TT>(x,y)</TT>, however, the intermediatecode becomes:</P><PRE><FONT COLOR="#0066FF">int x = 5, y = 7, z;z =7;</FONT></PRE><H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">Why All the Parentheses?</FONT></H4><P>You may be wondering why there are so many parentheses in many of the macros presentedso far. The preprocessor does not demand that parentheses be placed around the argumentsin the substitution string, but the parentheses help you to avoid unwanted side effectswhen you pass complicated values to a macro. For example, if you define <TT>MAX</TT>as</P><PRE><FONT COLOR="#0066FF">#define MAX(x,y) x &gt; y ? x : y</FONT></PRE><P>and pass in the values <TT>5</TT> and <TT>7</TT>, the macro works as intended.But if you pass in a more complicated expression, you'll get unintended results,as shown in Listing 17.3.</P><P><A NAME="Heading18"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 17.3. Usingparentheses in macros.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     // Listing 17.3 Macro Expansion2:     #include &lt;iostream.h&gt;3:4:     #define CUBE(a) ( (a) * (a) * (a) )5:     #define THREE(a) a * a * a6:7:     int main()8:     {9:        long x = 5;10:       long y = CUBE(x);11:       long z = THREE(x);12:13:       cout &lt;&lt; &quot;y: &quot; &lt;&lt; y &lt;&lt; endl;14:       cout &lt;&lt; &quot;z: &quot; &lt;&lt; z &lt;&lt; endl;15:16:       long a = 5, b = 7;17:       y = CUBE(a+b);18:       z = THREE(a+b);19:20:       cout &lt;&lt; &quot;y: &quot; &lt;&lt; y &lt;&lt; endl;21:       cout &lt;&lt; &quot;z: &quot; &lt;&lt; z &lt;&lt; endl;22:     return 0;<TT>23: }</TT></FONT><FONT COLOR="#0066FF">Output: y: 125z: 125y: 1728z: 82</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On line 4, the macro <TT>CUBE</TT>is defined, with the argument <TT>x</TT> put into parentheses each time it is used.On line 5, the macro <TT>THREE</TT> is defined, without the parentheses.<BR>In the first use of these macros, the value <TT>5</TT> is given as the parameter,and both macros work fine. <TT>CUBE(5)</TT> expands to <TT>( (5) * (5) * (5) )</TT>,which evaluates to <TT>125</TT>, and <TT>THREE(5)</TT> expands to <TT>5 * 5 * 5</TT>,which also evaluates to <TT>125</TT>.</P><P>In the second use, on lines 16-18, the parameter is <TT>5 + 7</TT>. In this case,<TT>CUBE(5+7)</TT> evaluates to</P><PRE><FONT COLOR="#0066FF">( (5+7) * (5+7) * (5+7) )</FONT></PRE><P>which evaluates to</P><PRE><FONT COLOR="#0066FF">( (12) * (12) * (12) )</FONT></PRE><P>which in turn evaluates to <TT>1728</TT>. <TT>THREE(5+7)</TT>, however, evaluatesto</P><PRE><FONT COLOR="#0066FF">5 + 7 * 5 + 7 * 5 + 7</FONT></PRE><P>Because multiplication has a higher precedence than addition, this becomes</P><PRE><FONT COLOR="#0066FF">5 + (7 * 5) + (7 * 5) + 7</FONT></PRE><P>which evaluates to</P><PRE><FONT COLOR="#0066FF">5 + (35) + (35) + 7</FONT></PRE><P>which finally evaluates to <TT>82</TT>.<H4 ALIGN="CENTER"><A NAME="Heading20"></A><FONT COLOR="#000077">Macros Versus Functionsand Templates</FONT></H4><P>Macros suffer from four problems in C++. The first is that they can be confusingif they get large, because all macros must be defined on one line. You can extendthat line by using the backslash character (<TT>\</TT>), but large macros quicklybecome difficult to manage.</P><P>The second problem is that macros are expanded inline each time they are used.This means that if a macro is used a dozen times, the substitution will appear 12times in your program, rather than appear once as a function call will. On the otherhand, they are usually quicker than a function call because the overhead of a functioncall is avoided.</P><P>The fact that they are expanded inline leads to the third problem, which is thatthe macro does not appear in the intermediate source code used by the compiler, andtherefore is unavailable in most debuggers. This makes debugging macros tricky.</P><P>The final problem, however, is the biggest: macros are not type-safe. While itis convenient that absolutely any argument may be used with a macro, this completelyundermines the strong typing of C++ and so is anathema to C++ programmers. However,there is a way to overcome this problem, as you'll see on Day 19, &quot;Templates.&quot;<H3 ALIGN="CENTER"><A NAME="Heading21"></A><FONT COLOR="#000077">Inline Functions</FONT></H3><P>It is often possible to declare an inline function rather than a macro. For example,Listing 17.4 creates a <TT>CUBE</TT> function, which accomplishes the same thingas the <TT>CUBE</TT> macro in Listing 17.3, but does so in a type-safe way.</P><P><A NAME="Heading22"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 17.4. Usinginline rather than a macro.</B></FONT></P><PRE><FONT COLOR="#0066FF">1:     #include &lt;iostream.h&gt;2:3:     inline unsigned long Square(unsigned long a) { return a * a; }4:     inline unsigned long Cube(unsigned long a) 5:         { return a * a * a; }6:     int main()7:     {8:        unsigned long x=1 ;9:        for (;;)10:       {11:          cout &lt;&lt; &quot;Enter a number (0 to quit): &quot;;12:          cin &gt;&gt; x;13:          if (x == 0)14:             break;15:          cout &lt;&lt; &quot;You entered: &quot; &lt;&lt; x;16:          cout &lt;&lt; &quot;.  Square(&quot; &lt;&lt; x &lt;&lt; &quot;): &quot;;17:          cout  &lt;&lt; Square(x);18:          cout&lt;&lt; &quot;. Cube(&quot; _&lt;&lt; x &lt;&lt; &quot;): &quot;;19:          cout &lt;&lt; Cube(x) &lt;&lt; &quot;.&quot; &lt;&lt; endl;20:       }21:     return 0;<TT>22: }</TT></FONT><FONT COLOR="#0066FF">Output: Enter a number (0 to quit): 1You entered: 1.  Square(1): 1. Cube(1): 1.Enter a number (0 to quit): 2You entered: 2.  Square(2): 4. Cube(2): 8.Enter a number (0 to quit): 3You entered: 3.  Square(3): 9. Cube(3): 27.

⌨️ 快捷键说明

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