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

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 5 页
字号:
</pre>
    <p>When a true <tt>const</tt> variable is explicitly cast to a non-<tt>const</tt> 
      variable, the result of an attempt to change its value is undefined. This 
      is because an implementation can store true <tt>const</tt> data in the read-only 
      memory, and an attempt to write to it usually triggers a hardware exception. 
      (Using an explicit cast to remove <tt>const</tt>ness does not change the 
      physical memory properties of a variable.) For example</p>
    <pre>
<tt>const int cnum = 0; //true const, may be stored in the machine's ROM</tt>
<tt>const int * pci = &amp;cnum;</tt>
<tt>int *pi  = const_cast&lt;int*&gt; (pci); // brute force attempt to unconst a variable</tt>
<tt>cout&lt;&lt; *pi; //OK, value of cnum is not modified</tt>
<tt>*pi = 2;  //undefined, an attempt to modify cnum which is a true const variable</tt>
</pre>
    <p>On the other hand, casting away the contractual <tt>const</tt>ness of an 
      object makes it possible to modify its value safely:</p>
    <pre>
<tt> int num = 0;</tt>
<tt> const int * pci = &amp;num;  // *pci is a contractual const int</tt>
<tt> int *pi  = const_cast&lt;int*&gt; (pci);   // get rid of contractual const</tt>
<tt> *pi = 2;    // OK, modify num's value</tt>
</pre>
    <p>To conclude, <tt>const_cast</tt> is used to remove the <tt>const</tt> or 
      <tt>volatile</tt> qualities of an object. The resultant value can be used 
      in a context that requires a non-<tt>const</tt> or <tt>volatile</tt> object. 
      The cast operation is safe as long as the resultant value is not modified. 
      It is possible to modify the value of the resultant object only if the original 
      operand is not truly <tt>const</tt>.</p>
    <h4> reinterpret_cast</h4>
    <p><tt>reinterpret_cast &lt;</tt><cite>to</cite><tt>&gt; (</tt><cite>from</cite><tt>)</tt> 
      is used in low-level, unsafe conversions. <tt>reinterpret_cast</tt> merely 
      returns a low-level reinterpretation of the bit pattern of its operand. 
      Note, however, that <tt>reinterpret_cast</tt> cannot alter the cv-qualification 
      of its operand. The use of <tt>reinterpret_cast</tt> is dangerous and highly 
      non-portable -- use it sparingly. Following are examples of <tt>reinterpret_cast</tt> 
      uses. </p>
    <p><tt>reinterpret_cast</tt> can be used to convert two pointers of completely 
      nonrelated types, as in</p>
    <pre>
<tt>#include &lt;cstdio&gt;</tt>
<tt>void mem_probe()</tt>
<tt>{</tt>
<tt>  long n = 1000000L; long *pl = &amp;n;</tt>
<tt>  unsigned char * pc = reinterpret_cast &lt;unsigned char *&gt; (pl);</tt>
<tt>  printf("%d %d %d %d", pc[0], pc[1], pc[2], pc[3]); //memory dump</tt>
<tt>}</tt>
</pre>
    <p><tt>reinterpret_cast</tt> can cast integers to pointers, and vice versa. 
      For example</p>
    <pre>
<tt>void *pv = reinterpret_cast&lt;void *&gt; (0x00fffd);</tt>
<tt> int ptr = reinterpret_cast&lt;int&gt; (pv);</tt>
</pre>
    <p><tt>reinterpret_cast</tt> can also be used for conversions between different 
      types of function pointers. The result of using the resultant pointer to 
      call a function with a nonmatching type is undefined.</p>
    <p>Do not use <tt>reinterpret_cast</tt> instead of <tt>static_cast</tt> -- 
      the results might be undefined. For example, using <tt>reinterpret_cast</tt> 
      to navigate through the class hierarchy of a multiply-inherited object is 
      likely to yield the wrong result. Consider the following:</p>
    <pre>
<tt>class A</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  int n;</tt>
<tt>};</tt>
<tt>class B</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  char c;</tt>
<tt>};</tt>
<tt>class C: public A, public B</tt>
<tt>{};</tt>
<tt>void func(B * pb)</tt>
<tt>{</tt>
<tt>  C *pc1 = static_cast&lt;C*&gt; (pb); //correct offset adjustment</tt>
<tt>  C *pc2 = reinterpret_cast&lt;C*&gt; (pb); //no offset calculated</tt>
<tt>}</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> B b;</tt>
<tt> func(&amp;b);</tt>
<tt>}</tt>
</pre>
    <p>On my machine, <tt>pc1</tt> is assigned the value <tt>0x0064fdf0</tt>, 
      whereas <tt>pc2</tt> is assigned <tt>0x0064fdf4</tt>. This demonstrates 
      the difference between the two cast operators. Using the information that 
      is available at compile time, <tt>static_cast</tt> converts a pointer to 
      <tt>B</tt> to a pointer to <tt>C</tt>. It does so by causing <tt>pc1</tt> 
      to point at the start of <tt>C</tt> by subtracting the offset of the subobject 
      <tt>B</tt>. On the other hand, <tt>reinterpret_cast</tt> simply assigns 
      the binary value of <tt>pb</tt> to <tt>pc2</tt>, without any further adjustments; 
      for this reason, it yields the wrong result.</p>
    <h4> dynamic_cast</h4>
    <p>In pre-standard C++, as was noted earlier, C-style cast was used to perform 
      a dynamic cast as well. The cast was either static or dynamic, depending 
      on the type of the operand. The Standardization committee, however, opposed 
      this approach. An expensive runtime operation that looked exactly like a 
      static cast (that is, penalty-free) can mislead the users. For this purpose, 
      a new operator was introduced to the language: <tt>dynamic_cast</tt> (<tt>dynamic_cast</tt> 
      is discussed in further detail in Chapter 7, "Runtime Type Identification"). 
      The name and the syntax of <tt>dynamic_cast</tt> were chosen to look markedly 
      different from C-style cast. All other new typecast operators follow this 
      model. Following is an example of <tt>dynamic_cast</tt>:</p>
    <pre>
<tt>Derived *p  = dynamic_cast&lt;derived *&gt; (&amp;base); //pointer form</tt>
<tt>Derived &amp; rd  = dynamic_cast&lt;derived &amp;&gt; (base); //reference form</tt>
</pre>
    <h4> Conclusions</h4>
    <p>The new typecasting operators are clearer and more explicit in their intended 
      purpose. A name such as <tt>dynamic_cast</tt><i>,</i> for example<i>,</i> 
      warns its users about its incurred runtime overhead. Most importantly, though, 
      the new cast operators are safer because they give the compiler a chance 
      to detect the programmer's mistakes.</p>
    <p>Users might find the proliferation of cast operators somewhat confusing. 
      In particular, the choice between <tt>static_cast</tt> and <tt>reinterpret_cast</tt> 
      might not seem immediately clear. How to choose? As a rule, <tt>static_cast</tt> 
      is the first choice. If the compiler refuses to accept it, use <tt>reinterpret_cast</tt> 
      instead.</p>
    <h3> <a name="Heading16">Built-in bool Type</a></h3>
    <p>The built-in <tt>bool</tt> data type was added to the Standard after consideration 
      of several other proposals. None of these was found satisfactory. Following 
      is an overview some of these proposals, which is in turn followed by a discussion 
      of the characteristics of the <tt>bool</tt> type.</p>
    <h4> typedef Boolean</h4>
    <p>One suggestion was to use a <tt>typedef</tt> for a Boolean data type:</p>
    <pre>
<tt>typedef int bool;</tt>
</pre>
    <p>However, a <tt>typedef</tt> that relies on another built-in type of the 
      language renders the Boolean type unusable with some language features. 
      For example, using it in function overloading can result in ambiguities:</p>
    <pre>
<tt>void f(bool);</tt>
<tt>void f(int);//error, redefinition of void f(bool);</tt>
</pre>
    <p>In addition, a <tt>typedef</tt> is not strongly-typed. Consequently, it 
      is impossible to ensure that only Boolean values are assigned to it in a 
      context that requires Boolean values.</p>
    <h4> enum Type</h4>
    <p>An alternative solution was to use an <tt>enum</tt> type:</p>
    <pre>
<tt>enum bool { false, true};</tt>
</pre>
    <p><tt>enum</tt>s are strongly-typed. However, the committee wanted to ensure 
      backward compatibility with old code that used <tt>int</tt> values as a 
      Boolean data type. For example</p>
    <pre>
<tt>#include &lt;ctype.h&gt;</tt>
<tt>enum bool {false, true};</tt>
<tt>void f()</tt>
<tt>{</tt>
<tt>  enum bool b;</tt>
<tt>  b = islower('a'); //compile time error, int assigned to an enum</tt>
<tt>}</tt>
</pre>
    <h4> Class bool</h4>
    <p>A third suggestion was to use a class such as the following:</p>
    <pre>
<tt>class bool</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  int val;</tt>
<tt>public:</tt>
<tt>  operator int();</tt>
<tt>};</tt>
</pre>
    <p>Such a class guarantees type uniqueness, so it can be used to overload 
      functions and to specialize templates. In addition, it is backward compatible 
      with Boolean integers. There are, however, several drawbacks to the class 
      approach. First, users are required to <tt>#include</tt> a dedicated header 
      and to link their programs with the compiled code of the class. Worse yet, 
      the conversion operator might interfere with user-defined conversion operators 
      that are defined in other classes. Finally, a full-blown class that defines 
      constructors and conversion operators is significantly less efficient than 
      a fundamental type. For these reasons, the Standardization committee decided 
      to add a new built-in type.</p>
    <h4> A Built-in Type bool</h4>
    <p><tt>bool</tt> is an implementation-dependent integral type that can hold 
      either a <tt>true</tt> or a <tt>false</tt> value. A standardized Boolean 
      type has several advantages:</p>
    <ul>
      <li> 
        <p> <b>Portability</b> -- All Standard compliant compilers support <tt>bool</tt> 
          type. When code is ported to different platforms, it will work as expected.</p>
      </li>
      <p></p>
      <li> <b>Readability</b> -- The use of explicit keywords such as <tt>true</tt>, 
        <tt>false</tt>, and <tt>bool</tt> is self-documenting and is more evident 
        than the use of <tt>int</tt> values.</li>
      <p></p>
      <li> <b>Type Distinctness</b> -- Because <tt>bool</tt> is a distinct type, 
        the following functions are now also distinct:</li>
    </ul>
    <p></p>
    <pre>
<tt>void f(bool b);</tt>
<tt>void f(int n);</tt>
</pre>
    <ul>
      <li> <b>Performance</b> -- Memory usage can be optimized by the implementation, 
        which is allowed to use a single byte to represent a <tt>bool</tt> instead 
        of an <tt>int</tt>. In addition, the use of a built-in type rather than 
        a class also ensures the highest performance.</li>
    </ul>
    <p></p>
    <p>With the introduction of the <tt>bool</tt> data type, built-in operators 
      were modified accordingly to work with <tt>bool</tt> values. The logical 
      operators <tt>&amp;&amp;</tt>, <tt>||</tt>, and <tt>!</tt> now take <tt>bool</tt> 
      values as arguments and return <tt>bool</tt> results. Similarly, the relational 
      operators <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>&lt;=</tt>, <tt>&gt;=</tt>, 
      <tt>==</tt>, and <tt>!=</tt> return <tt>bool</tt> results. In addition, 
      <tt>iostream</tt> classes were adjusted to support the new type.</p>
    <p><b>(f)Viewing <tt>bool</tt> Variables as Literals</b></p>
    <p>By default, <tt>iostream</tt> objects display <tt>bool</tt> variables as 
      <tt>0</tt> and <tt>1</tt>. It is possible to override the default setting 
      by inserting the formatting flag <tt>boolalpha</tt> to the stream object. 
      Subsequently, the symbolic representations <tt>false</tt> and <tt>true</tt> 
      are displayed instead of <tt>0</tt> and <tt>1</tt>. For example</p>
    <pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>using namespace std;</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  bool b = true;</tt>
<tt>  cout&lt;&lt;b;  // default setting; display 1</tt>
<tt>  cout&lt;&lt;boolalpha; //henceforth, display 'true' and 'false' instead of 1 and 0</tt>
<tt>  cout&lt;&lt;b;   // output: true</tt>
<tt>  cout&lt;&lt;!b;   // output: false</tt>
<tt>  return 0;</tt>
<tt>}</tt>
</pre>
    <h3> <a name="Heading17">Exception Handling</a></h3>
    <p>Exception handling is used to report and handle runtime errors. Supplementary 
      features, namely <i>exception specifications</i> and <i>function </i><tt>try</tt><i> 
      blocks</i>, were added to the Standard in recent years. The following sections 
      provide a brief overview of these features. (Exception handling and the 
      supplementary features are discussed in more detail in Chapter 6, "Exception 
      Handling.")</p>
    <h4> Exception Specification</h4>
    <p>A function can indicate the potential exceptions it can throw by specifying 
      a list of these exceptions. Exception specifications are particularly useful 
      when users of such a function can only view its prototype but cannot access 
      its source file. Following is an example of specifying an exception:</p>
    <pre>
<tt>class Zerodivide{/*..*/};</tt>
<tt>int divide (int, int) throw(Zerodivide);   //function may throw an exception</tt>
<tt>                                           //of type Zerodivide, but no other</tt>
</pre>
    <h4> Function try Blocks</h4>

⌨️ 快捷键说明

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