📄 chapter10.html
字号:
<font color=#009900>// to select Math::a :</font>
Math::a.setSign(positive);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Suppose you have a second namespace that
contains some of the names in <B>namespace Math</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:NamespaceOverriding2.h</font>
#ifndef NAMESPACEOVERRIDING2_H
#define NAMESPACEOVERRIDING2_H
#include <font color=#004488>"NamespaceInt.h"</font>
<font color=#0000ff>namespace</font> Calculation {
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> Int;
Integer divide(Integer, Integer);
<font color=#009900>// ...</font>
}
#endif <font color=#009900>// NAMESPACEOVERRIDING2_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since this namespace is also introduced
with a <B>using</B> directive, you have the possibility of a collision. However,
the ambiguity <A NAME="Index1782"></A><A NAME="Index1783"></A>appears at the
point of <I>use</I> of the name, not at the <B>using</B>
directive:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:OverridingAmbiguity.cpp</font>
#include <font color=#004488>"NamespaceMath.h"</font>
#include <font color=#004488>"NamespaceOverriding2.h"</font>
<font color=#0000ff>void</font> s() {
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> Math;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> Calculation;
<font color=#009900>// Everything's ok until:</font>
<font color=#009900>//! divide(1, 2); // Ambiguity</font>
}
<font color=#0000ff>int</font> main() {} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Thus, it’s possible to write
<B>using</B> directives to introduce a number of namespaces with conflicting
names without ever producing an ambiguity.</FONT><BR></P></DIV>
<A NAME="Heading310"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
The using declaration</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can inject names one at a time into
the current scope with a <I>using
declaration<A NAME="Index1784"></A><A NAME="Index1785"></A><A NAME="Index1786"></A></I>.
Unlike the <B>using</B> directive, which treats names as if they were declared
globally to the scope, a <B>using</B> declaration is a declaration within the
current scope. This means it can override names from a <B>using</B>
directive:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:UsingDeclaration.h</font>
#ifndef USINGDECLARATION_H
#define USINGDECLARATION_H
<font color=#0000ff>namespace</font> U {
<font color=#0000ff>inline</font> <font color=#0000ff>void</font> f() {}
<font color=#0000ff>inline</font> <font color=#0000ff>void</font> g() {}
}
<font color=#0000ff>namespace</font> V {
<font color=#0000ff>inline</font> <font color=#0000ff>void</font> f() {}
<font color=#0000ff>inline</font> <font color=#0000ff>void</font> g() {}
}
#endif <font color=#009900>// USINGDECLARATION_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:UsingDeclaration1.cpp</font>
#include <font color=#004488>"UsingDeclaration.h"</font>
<font color=#0000ff>void</font> h() {
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> U; <font color=#009900>// Using directive</font>
<font color=#0000ff>using</font> V::f; <font color=#009900>// Using declaration</font>
f(); <font color=#009900>// Calls V::f();</font>
U::f(); <font color=#009900>// Must fully qualify to call</font>
}
<font color=#0000ff>int</font> main() {} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>using</B> declaration just gives
the fully specified name of the identifier, but no type information. This means
that if the namespace contains a set of
<A NAME="Index1787"></A><A NAME="Index1788"></A>overloaded functions with the
same name, the <B>using</B> declaration declares all the functions in the
overloaded set.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can put a <B>using</B> declaration
anywhere a normal declaration can occur. A <B>using</B> declaration works like a
normal declaration in all ways but one: because you don’t give an argument
list, it’s possible for a <B>using</B> declaration to cause the overload
<A NAME="Index1789"></A>of a function with the same argument types (which
isn’t allowed with normal overloading). This ambiguity, however,
doesn’t show up until the point of use, rather than the point of
declaration.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A <B>using</B> declaration can also
appear within a namespace, and it has the same effect as anywhere else –
that name is declared within the space:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:UsingDeclaration2.cpp</font>
#include <font color=#004488>"UsingDeclaration.h"</font>
<font color=#0000ff>namespace</font> Q {
<font color=#0000ff>using</font> U::f;
<font color=#0000ff>using</font> V::g;
<font color=#009900>// ...</font>
}
<font color=#0000ff>void</font> m() {
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> Q;
f(); <font color=#009900>// Calls U::f();</font>
g(); <font color=#009900>// Calls V::g();</font>
}
<font color=#0000ff>int</font> main() {} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A <B>using</B> declaration is an alias,
and it allows you to declare the same function in separate namespaces. If you
end up re-declaring the same function by importing different namespaces,
it’s OK – there won’t be any ambiguities or
duplications.</FONT><A NAME="_Toc472654922"></A><BR></P></DIV>
<A NAME="Heading311"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
The use of namespaces</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Some of the rules above may seem a bit
daunting at first, especially if you get the impression that you’ll be
using them all the time. In general, however, you can get away with very simple
usage of namespaces as long as you understand how they work. The key thing to
remember is that when you introduce a global <B>using</B> directive (via a
“<B>using namespace</B>” outside of any scope) you have thrown open
the namespace for that file. This is usually fine for an implementation file (a
“<B>cpp</B>” file) because the <B>using</B> directive is only in
effect until the end of the compilation of that file. That is, it doesn’t
affect any other files, so you can adjust the control of the namespaces one
implementation file at a time. For example, if you discover a name clash because
of too many <B>using</B> directives in a particular implementation file, it is a
simple matter to change that file so that it uses explicit qualifications or
<B>using</B> declarations to eliminate the clash, without modifying other
implementation files.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index1790"></A><A NAME="Index1791"></A><FONT FACE="Georgia">Header
files are a different issue. You virtually never want to introduce a global
<B>using</B> directive into a header file, because that would mean that any
other file that included your header would also have the namespace thrown open
(and header files can include other header files). </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So, in header files you should either use
explicit qualification or scoped <B>using</B> directives and <B>using</B>
declarations. This is the practice that you will find in this book, and by
following it you will not “pollute” the global namespace and throw
yourself back into the pre-namespace world of C++.
</FONT><A NAME="_Toc305593221"></A><A NAME="_Toc305628693"></A><A NAME="_Toc312373948"></A><A NAME="_Toc472654923"></A><BR></P></DIV>
<A NAME="Heading312"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Static members in
C++<BR><A NAME="Index1792"></A><A NAME="Index1793"></A><A NAME="Index1794"></A><A NAME="Index1795"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are times when you need a single
storage space to be used by all objects of a class. In C, you would use a global
variable, but this is not very safe. Global data can be modified by anyone, and
its name can clash with other identical names in a large project. It would be
ideal if the data could be stored as if it were global, but be hidden inside a
class, and clearly associated with that class.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is accomplished with <B>static</B>
data members inside a class. There is a single piece of storage for a
<B>static</B> data member, regardless of how many objects of that class you
create. All objects share the same <B>static</B> storage space for that data
member, so it is a way for them to “communicate” with each other.
But the <B>static</B> data belongs to the class; its name is scoped inside the
class and it can be <B>public</B>, <B>private</B>, or
<B>protected</B>.</FONT><A NAME="_Toc312373949"></A><A NAME="_Toc472654924"></A><BR></P></DIV>
<A NAME="Heading313"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Defining storage for static data
members<BR><A NAME="Index1796"></A><A NAME="Index1797"></A><A NAME="Index1798"></A><A NAME="Index1799"></A><A NAME="Index1800"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because <B>static</B> data has a single
piece of storage regardless of how many objects are created, that storage must
be defined in a single place. The compiler will not allocate storage for you.
The linker will report an error if a <B>static</B> data member is declared but
not defined.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The definition must occur outside the
class (no inlining is allowed), and only one definition is allowed. Thus, it is
common to put it in the implementation file for the class. The syntax sometimes
gives people trouble, but it is actually quite logical. For example, if you
create a static data member inside a class like this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>class</font> A {
<font color=#0000ff>static</font> <font color=#0000ff>int</font> i;
<font color=#0000ff>public</font>:
<font color=#009900>//...</font>
}; </PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Then you must define storage for that
static data member in the definition file like this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font> A::i = 1;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you were to define an ordinary global
variable, you would say</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font> i = 1;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">but here, the scope resolution operator
and the class name are used to specify <B>A::i</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Some people have trouble with the idea
that <B>A::i</B> is <B>private</B>, and yet here’s something that seems to
be manipulating it right out in the open. Doesn’t this break the
protection mechanism? It’s a completely safe practice for two reasons.
First, the only place this initialization is legal is in the definition. Indeed,
if the <B>static</B> data were an object with a constructor, you would call the
constructor instead of using the <B>=</B> operator. Second, once the definition
has been made, the end-user cannot make a second definition – the linker
will report an error. And the class creator is forced to create the definition
or the code won’t link during testing. This ensures that the definition
happens only once and that it’s in the hands of the class
creator.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The entire initialization expression for
a static member <A NAME="Index1801"></A><A NAME="Index1802"></A>is in the scope
of the class. For example,</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C10:Statinit.cpp</font>
<font color=#009900>// Scope of static initializer</font>
#include <iostream>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>int</font> x = 100;
<font color=#0000ff>class</font> WithStatic {
<font color=#0000ff>static</font> <font color=#0000ff>int</font> x;
<font color=#0000ff>static</font> <font color=#0000ff>int</font> y;
<font color=#0000ff>public</font>:
<font color=#0000ff>void</font> print() <font color=#0000ff>const</font> {
cout << <font color=#004488>"WithStatic::x = "</font> << x << endl;
cout << <font color=#004488>"WithStatic::y = "</font> << y << endl;
}
};
<font color=#0000ff>int</font> WithStatic::x = 1;
<font color=#0000ff>int</font> WithStatic::y = x + 1;
<font color=#009900>// WithStatic::x NOT ::x</font>
<font color=#0000ff>int</font> main() {
WithStatic ws;
ws.print();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here, the qualification
<B>WithStatic::</B> extends the scope of <B>WithStatic</B> to the entire
definition.</FONT><BR></P></DIV>
<A NAME="Heading314"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
static array initialization</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Chapter 8 introduced the <B>static
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -