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

📄 tij0168.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 5 页
字号:
          translateHex(URLstr[i + 1]) * 16 +
          translateHex(URLstr[i + 2]);
        i += 2; <font color="#009900">// Move past hex code</font>
      } <font color="#0000ff">else</font> <font color="#009900">// An ordinary character</font>
        result[j] = URLstr[i];
    }
    <font color="#0000ff">return</font> result;
  }
  <font color="#009900">// Translate a single hex character; used by</font>
  <font color="#009900">// decodeURLString():</font>
  <font color="#0000ff">static</font> <font color="#0000ff">char</font> translateHex(<font color="#0000ff">char</font> hex) {
    <font color="#0000ff">if</font>(hex &gt;= 'A')
      <font color="#0000ff">return</font> (hex &amp; 0xdf) - 'A' + 10;
    <font color="#0000ff">else</font>
      <font color="#0000ff">return</font> hex - '0';
  }
};

<font color="#009900">// Parses any CGI query and turns it</font>
<font color="#009900">// into an STL vector of Pair objects:</font>
<font color="#0000ff">class</font> CGI_vector : <font color="#0000ff">public</font> vector&lt;Pair&gt; {
  <font color="#0000ff">char</font>* qry;
  <font color="#0000ff">const</font> <font color="#0000ff">char</font>* start; <font color="#009900">// Save starting position</font>
  <font color="#009900">// Prevent assignment and copy-construction:</font>
  <font color="#0000ff">void</font> operator=(CGI_vector&amp;);
  CGI_vector(CGI_vector&amp;);
<font color="#0000ff">public</font>:
  <font color="#009900">// const fields must be initialized in the C++</font>
  <font color="#009900">// "Constructor initializer list":</font>
  CGI_vector(<font color="#0000ff">char</font>* query) :
      start(<font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(query) + 1]) {
    qry = (<font color="#0000ff">char</font>*)start; <font color="#009900">// Cast to non-const</font>
    strcpy(qry, query);
    Pair p;
    <font color="#0000ff">while</font>((p = nextPair()) != 0)
      push_back(p);
  }
  <font color="#009900">// Destructor:</font>
  ~CGI_vector() { delete start; }
<font color="#0000ff">private</font>:
  <font color="#009900">// Produces name-value pairs from the query </font>
  <font color="#009900">// string. Returns an empty Pair when there's </font>
  <font color="#009900">// no more query string left:</font>
  Pair nextPair() {
    <font color="#0000ff">char</font>* name = qry;
    <font color="#0000ff">if</font>(name == 0 || *name == '\0')
      <font color="#0000ff">return</font> Pair(); <font color="#009900">// End, return null Pair</font>
    <font color="#0000ff">char</font>* value = strchr(name, '=');
    <font color="#0000ff">if</font>(value == 0)
      <font color="#0000ff">return</font> Pair(); <font color="#009900">// Error, return null Pair</font>
    <font color="#009900">// Null-terminate name, move value to start</font>
    <font color="#009900">// of its set of characters:</font>
    *value = '\0';
    value++;
    <font color="#009900">// Look for end of value, marked by '&amp;':</font>
    qry = strchr(value, '&amp;');
    <font color="#0000ff">if</font>(qry == 0) qry = ""; <font color="#009900">// Last pair found</font>
    <font color="#0000ff">else</font> {
      *qry = '\0'; <font color="#009900">// Terminate value string</font>
      qry++; <font color="#009900">// Move to next pair</font>
    }
    <font color="#0000ff">return</font> Pair(name, value);
  }
}; <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">After
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>#include</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statements, you see a line that says:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">using
namespace std;
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Namespaces
in C++ solve one of the problems taken care of by the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>package</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
scheme in Java: hiding library names. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>std</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
namespace refers to the Standard C++ library, and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is in this library so the line is required.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class starts out looking pretty simple: it just holds two (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">character
pointers, one for the name and one for the value. The default constructor
simply sets these pointers to zero, since in C++ an object&#8217;s memory
isn&#8217;t automatically zeroed. The second constructor calls the method 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>decodeURLString(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that produces a decoded string in newly-allocated heap memory. This memory must
be managed and destroyed by the object, as you will see in the destructor. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>name(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>value(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods produce read-only pointers to the respective fields. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>empty(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is a way for you to ask the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object whether either of its fields are empty; it returns a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>bool,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
which is C++&#8217;s built-in primitive Boolean data type. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator
bool(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
uses a special case of <A NAME="Index2794"></A><A NAME="Index2795"></A>C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>operator
overloading
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which allows you to control automatic type conversion. If you have a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object called 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>p</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and you use it in an expression in which a Boolean result is expected, such as 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>if(p)
{ //...
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
then the compiler will recognize that it has a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and it needs a Boolean, so it will automatically call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator
bool(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to perform the necessary conversion.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next three methods are part of the bookkeeping that&#8217;s necessary when you
create a class in C++. In the so-called &#8220;canonical form&#8221; for a C++
class, you must define the necessary &#8220;ordinary&#8221; constructors as
well as a copy-constructor and the assignment operator, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator=
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(and
the destructor, to clean up the memory). You must define these because they can
be quietly called by the compiler when you pass objects in and out of a
function (this calls the copy-constructor) or when you assign objects (the
assignment operator). Once you&#8217;ve gone through the trouble to understand
how the copy-constructor and assignment operator work you can write robust
classes in C++, but it is a bit of a learning experience.
</FONT><A NAME="fnB67" HREF="#fn67">[67]</A><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
<A NAME="Index2796"></A><A NAME="Index2797"></A>copy-constructor
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair(const
Pair&amp;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is automatically called whenever you pass an object into or out of a function 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>by
value
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
That is, you aren&#8217;t passing the address of the object you&#8217;re making
a copy of the whole object inside the function frame. This isn&#8217;t an
option in Java since you pass only handles, thus there&#8217;s no
copy-constructor in Java. (If you want to make a local duplicate, you 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the object &#8211; see Chapter 12.) Likewise, if you assign a handle in Java,
it&#8217;s simply copied. But assignment in C++ means that the entire object is
copied. In the copy-constructor, you create new storage and copy the source
data, but with the assignment operator you must release the old storage before
allocating new storage. What you&#8217;re seeing is probably the worst-case
complexity scenario for a C++ class, but it&#8217;s one of the reasons Java
proponents can argue that Java is a lot simpler than C++. In Java you pass
handles and there&#8217;s a garbage collector, so you don&#8217;t have to do
this kind of thing.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
isn&#8217;t quite the whole story. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class is using 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char*</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>nm</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>val</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and the worst-case complexity occurs primarily around pointers. If you use the
more modern Standard C++ 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>string</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class instead of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char*</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
things get much simpler (however, not all compilers have caught up enough to
come with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>string</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).
Then, the first part of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
looks like this:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#0000ff">class</font> Pair {
  string nm;
  string val;
<font color="#0000ff">public</font>:
  Pair() { }
  Pair(<font color="#0000ff">char</font>* name, <font color="#0000ff">char</font>* value) {
    <font color="#009900">// Creates new memory:</font>
    nm = decodeURLString(name);
    val = decodeURLString(value);
  }
  <font color="#0000ff">const</font> <font color="#0000ff">char</font>* name() <font color="#0000ff">const</font> { <font color="#0000ff">return</font> nm.c_str(); }
  <font color="#0000ff">const</font> <font color="#0000ff">char</font>* value() <font color="#0000ff">const</font> { <font color="#0000ff">return</font> val.c_str(); }
  <font color="#009900">// Test for "emptiness"</font>
  bool empty() <font color="#0000ff">const</font> {
    <font color="#0000ff">return</font> (nm.length() == 0) || (val.length() == 0);
  }
  <font color="#009900">// Automatic type conversion for boolean test:</font>
  operator bool() <font color="#0000ff">const</font> {
    <font color="#0000ff">return</font> (nm.length() != 0) &amp;&amp; (val.length() != 0);
  } </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(Also,
for this case 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>decodeURLString(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returns a 

⌨️ 快捷键说明

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