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

📄 chapter08.html

📁 Thinking in c++ 2nd edition,c++编程思想(第2版)
💻 HTML
📖 第 1 页 / 共 5 页
字号:
  <font color=#009900>// OK: g2 takes a const reference:</font>
  g2(f());
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><A NAME="_Toc305628678"></A><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>f(&#160;)</B> returns an object of
<B>class X</B> <A NAME="Index1535"></A><I>by value</I>. That means when you
immediately take the return value of <B>f(&#160;)</B> and pass it to another
function as in the calls to <B>g1(&#160;)</B> and <B>g2(&#160;)</B>, a temporary
is created and that temporary is <B>const</B>. Thus, the call in
<B>g1(&#160;)</B> is an error because <B>g1(&#160;)</B> doesn&#8217;t take a
<B>const</B> reference, but the call to <B>g2(&#160;)</B> is
OK.</FONT><A NAME="_Toc312373916"></A><A NAME="_Toc472654890"></A><BR></P></DIV>
<A NAME="Heading265"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Classes</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This section shows the ways you can use
<B>const</B> with <A NAME="Index1536"></A>classes. You may want to create a
local <B>const</B> in a class to use inside constant expressions that will be
evaluated at compile time. However, the meaning of <B>const</B> is different
inside classes, so you must understand the options in order to create
<B>const</B> data members of a class.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can also make an entire object
<B>const</B> (and as you&#8217;ve just seen, the compiler always makes temporary
objects <B>const</B>). But preserving the <B>const</B>ness of an object is more
complex. The compiler can ensure the <B>const</B>ness of a built-in type but it
cannot monitor the intricacies of a class. To guarantee the <B>const</B>ness of
a class object, the <B>const</B> member function is introduced: only a
<B>const</B> member function
<A NAME="Index1537"></A><A NAME="Index1538"></A><A NAME="Index1539"></A>may be
called for a <B>const</B> object.
</FONT><A NAME="_Toc312373917"></A><A NAME="_Toc472654891"></A><BR></P></DIV>
<A NAME="Heading266"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
const in
classes<BR><A NAME="Index1540"></A><A NAME="Index1541"></A><A NAME="Index1542"></A><A NAME="Index1543"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the places you&#8217;d like to use
a <B>const</B> for constant expressions is inside classes. The typical example
is when you&#8217;re creating an <A NAME="Index1544"></A>array inside a class
and you want to use a <B>const</B> instead of a
<A NAME="Index1545"></A><B>#define</B> to establish the array size and to use in
calculations involving the array. The array size is something you&#8217;d like
to keep hidden inside the class, so if you used a name like <B>size</B>, for
example, you could use that name in another class without a clash. The
preprocessor treats all <B>#define</B>s as global from the point they are
defined, so this will not achieve the desired effect. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You might assume that the logical choice
is to place a <B>const</B> inside the class. This doesn&#8217;t produce the
desired result. Inside a class, <B>const</B> partially reverts to its meaning in
C. It allocates storage within each object and represents a value that is
initialized once and then cannot change. The use of <B>const</B> inside a class
means &#8220;This is constant for the lifetime of the object.&#8221; However,
each different object may contain a different value for that
constant.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Thus, when you create an ordinary
(non-<B>static</B>) <B>const</B> inside a class, you cannot give it an initial
value. This initialization must occur in the constructor, of course, but in a
special place in the constructor. Because a <B>const</B> must be initialized at
the point it is created, inside the main body of the constructor the
<B>const</B> must <I>already </I>be initialized. Otherwise you&#8217;re left
with the choice of waiting until some point later in the constructor body, which
means the <B>const</B> would be un-initialized for a while. Also, there would be
nothing to keep you from changing the value of the <B>const</B> at various
places in the constructor body.</FONT><BR></P></DIV>
<A NAME="Heading267"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
The constructor initializer list</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The special initialization point is
called the <I>constructor initializer
list<A NAME="Index1546"></A><A NAME="Index1547"></A><A NAME="Index1548"></A><A NAME="Index1549"></A></I>,
and it was originally developed for use in inheritance (covered in Chapter 14).
The constructor initializer list &#8211; which, as the name implies, occurs only
in the definition of the constructor &#8211; is a list of &#8220;constructor
calls&#8221; that occur after the function argument list and a colon, but before
the opening brace of the constructor body. This is to remind you that the
initialization in the list occurs before any of the main constructor code is
executed. This is the place to put all <B>const</B> initializations. The proper
form for <B>const</B> inside a class is shown here:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:ConstInitialization.cpp</font>
<font color=#009900>// Initializing const in classes</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Fred {
  <font color=#0000ff>const</font> <font color=#0000ff>int</font> size;
<font color=#0000ff>public</font>:
  Fred(<font color=#0000ff>int</font> sz);
  <font color=#0000ff>void</font> print();
};

Fred::Fred(<font color=#0000ff>int</font> sz) : size(sz) {}
<font color=#0000ff>void</font> Fred::print() { cout &lt;&lt; size &lt;&lt; endl; }

<font color=#0000ff>int</font> main() {
  Fred a(1), b(2), c(3);
  a.print(), b.print(), c.print();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The form of the constructor initializer
list shown above is confusing at first because you&#8217;re not used to seeing a
built-in type treated as if it has a constructor.</FONT><BR></P></DIV>
<A NAME="Heading268"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
&#8220;Constructors&#8221; for built-in types</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As the language developed and more effort
was put into making user-defined types look like
<A NAME="Index1550"></A>built-in types, it became apparent that there were times
when it was helpful to make built-in types look like user-defined types. In the
constructor initializer list, you can treat a built-in type as if it has a
constructor, like this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:BuiltInTypeConstructors.cpp</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> B {
  <font color=#0000ff>int</font> i;
<font color=#0000ff>public</font>:
  B(<font color=#0000ff>int</font> ii);
  <font color=#0000ff>void</font> print();
};

B::B(<font color=#0000ff>int</font> ii) : i(ii) {}
<font color=#0000ff>void</font> B::print() { cout &lt;&lt; i &lt;&lt; endl; }

<font color=#0000ff>int</font> main() {
  B a(1), b(2);
  <font color=#0000ff>float</font> pi(3.14159);
  a.print(); b.print();
  cout &lt;&lt; pi &lt;&lt; endl;
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is especially critical when
initializing <B>const</B> data members
<A NAME="Index1551"></A><A NAME="Index1552"></A><A NAME="Index1553"></A><A NAME="Index1554"></A>because
they must be initialized before the function body is entered.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It made sense to extend this
&#8220;constructor&#8221; for built-in types (which simply means assignment) to
the general case, which is why the <B>float pi(3.14159)</B> definition works in
the above code.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;s often useful to encapsulate a
built-in type inside a class to guarantee initialization with the constructor.
For example, here&#8217;s an <B>Integer</B> class:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:EncapsulatingTypes.cpp</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Integer {
  <font color=#0000ff>int</font> i;
<font color=#0000ff>public</font>:
  Integer(<font color=#0000ff>int</font> ii = 0);
  <font color=#0000ff>void</font> print();
};

Integer::Integer(<font color=#0000ff>int</font> ii) : i(ii) {}
<font color=#0000ff>void</font> Integer::print() { cout &lt;&lt; i &lt;&lt; ' '; }

<font color=#0000ff>int</font> main() {
  Integer i[100];
  <font color=#0000ff>for</font>(<font color=#0000ff>int</font> j = 0; j &lt; 100; j++)
    i[j].print();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The array of <B>Integer</B>s in
<B>main(&#160;)</B> are all automatically initialized to zero. This
initialization <A NAME="Index1555"></A>isn&#8217;t necessarily more costly than
a <B>for</B> loop or <B>memset(&#160;)<A NAME="Index1556"></A></B>. Many
compilers easily optimize this to a very fast
process.</FONT><A NAME="_Toc312373918"></A><A NAME="_Toc472654892"></A><BR></P></DIV>
<A NAME="Heading269"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Compile-time constants in
classes<BR><A NAME="Index1557"></A><A NAME="Index1558"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The above use of <B>const</B> is
interesting and probably useful in cases, but it does not solve the original
problem which is: &#8220;how do you make a compile-time constant inside a
class?&#8221; The answer requires the use of an additional keyword which will
not be fully introduced until Chapter 10: <B>static</B>. The <B>static</B>
keyword, in this situation, means &#8220;there&#8217;s only one instance,
regardless of how many objects of the class are created,&#8221; which is
precisely what we need here: a member of a class which is constant, and which
cannot change from one object of the class to another. Thus, a
<A NAME="Index1559"></A><B>static const </B>of a built-in type can be treated as
a compile-time constant.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There is one feature of <B>static
const</B> when used inside classes which is a bit unusual: you must provide the
<A NAME="Index1560"></A>initializer at the point of definition of the <B>static
const</B>. This is something that only occurs with the <B>static const</B>; as
much as you might like to use it in other situations it won&#8217;t work because
all other data members must be initialized in the constructor or in other member
functions.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here&#8217;s an example that shows the
creation and use of a <B>static const</B> called <B>size</B> inside a class that
represents a stack of string
pointers</FONT><A NAME="fnB44" HREF="#fn44">[44]</A><FONT FACE="Georgia">:
</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:StringStack.cpp</font>
<font color=#009900>// Using static const to create a </font>
<font color=#009900>// compile-time constant inside a class</font>
#include &lt;string&gt;
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> StringStack {
  <font color=#0000ff>static</font> <font color=#0000ff>const</font> <font color=#0000ff>int</font> size = 100;
  <font color=#0000ff>const</font> string* stack[size];
  <font color=#0000ff>int</font> index;
<font color=#0000ff>public</fon

⌨️ 快捷键说明

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