📄 index.html
字号:
<tt>int main()</tt>
<tt>{</tt>
<tt> using namespace excelSoftCompany;</tt>
<tt> string s; //referring to class excelSoftCompany::string</tt>
<tt> std::string standardstr; //now instantiate an ANSI string</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<h3> <a name="Heading7">Namespaces Can Be Extended </a></h3>
<p>The C++ standardization committee was well aware of the fact that related declarations
can span across several translation units. Therefore, a namespace can be defined
in parts. For example</p>
<pre>
<tt> //file proj_const.h</tt>
<tt>namespace MyProj </tt>
<tt>{</tt>
<tt> enum NetProtocols</tt>
<tt> {</tt>
<tt> TCP_IP,</tt>
<tt> HTTP,</tt>
<tt> UDP</tt>
<tt> }; // enum</tt>
<tt>}</tt>
<tt> //file proj_classes.h</tt>
<tt>namespace MyProj</tt>
<tt>{ // extending MyProj namespace</tt>
<tt> class RealTimeEncoder{ public: NetProtocols detect(); };</tt>
<tt> class NetworkLink {}; //global</tt>
<tt> class UserInterface {};</tt>
<tt>}</tt>
</pre>
<p>In a separate file, the same namespace can be extended with additional declarations.</p>
<p>The complete namespace <tt>MyProj</tt> can be extracted from both files as
follows:</p>
<pre>
<tt> //file app.cpp</tt>
<tt>#include "proj_const.h"</tt>
<tt>#include "proj_classes.h"</tt>
<tt>int main() </tt>
<tt>{</tt>
<tt> using namespace MyProj;</tt>
<tt> RealTimeEncoder encoder;</tt>
<tt> NetProtocols protocol = encoder.detect();</tt>
<tt> return 0;</tt>
<tt>} </tt>
</pre>
<h3> <a name="Heading8">Namespace Aliases</a></h3>
<p>As you have observed, choosing a short name for a namespace can eventually
lead to a name clash. However, very long namespaces are not easy to use. For
this purpose,<i> </i>a <i>namespace alias</i> can be used. The following example
defines the alias <tt>ESC</tt> for the unwieldy <tt>Excel_Software_Company</tt>
namespace. Namespace aliases have other useful purposes, as you will see soon.</p>
<pre>
<tt>//file decl.h</tt>
<tt>namespace Excel_Software_Company </tt>
<tt>{</tt>
<tt> class Date {/*..*/};</tt>
<tt> class Time {/*..*/};</tt>
<tt>}</tt>
<tt>//file calendar.cpp</tt>
<tt>#include "decl.h"</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> namespace ESC = Excel_Software_Company; //ESC is an alias for </tt>
<tt> // Excel_Software_Company</tt>
<tt> ESC::Date date;</tt>
<tt> ESC::Time time;</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<h3> <a name="Heading9">Koenig Lookup</a></h3>
<p>Andrew Koenig, one of the creators of C++, devised an algorithm for resolving
namespace members' lookup. This algorithm, also called <i>argument dependent
lookup</i>, is used in all standard-compliant compilers to handle cases such
as the following:</p>
<blockquote>
<hr>
<strong>CAUTION: </strong> Please note that some existing compilers do not yet
fully support Koenig lookup. Consequently, the following programs -- which rely
on Koenig lookup -- might not compile under compilers that are not fully compliant
to the ANSI/ISO standard in this respect.
<hr>
</blockquote>
<pre>
<tt>namespace MINE</tt>
<tt>{</tt>
<tt> class C {};</tt>
<tt> void func;</tt>
<tt>}</tt>
<tt>MINE::C c; // global object of type MINE::C</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> func( c ); // OK, MINE::f called</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<p>Neither a <tt>using</tt> declaration nor a <tt>using</tt> directive exists
in the program. Still, the compiler did the right thing -- it correctly identified
the unqualified name <tt>func</tt> as the function declared in namespace <tt>MINE</tt>
by applying Koenig lookup. </p>
<p>Koenig lookup instructs the compiler to look not just at the usual places,
such as the local scope, but also at the namespace that contains the argument's
type. Therefore, in the following source line, the compiler detects that the
object <tt>c</tt>, which is the argument of the function <tt>func()</tt>, belongs
to namespace <tt>MINE</tt>. Consequently, the compiler looks at namespace <tt>MINE</tt>
to locate the declaration of <tt>func()</tt>, "guessing" the programmer's intent:</p>
<pre>
<tt>func( c ); // OK, MINE::f called</tt>
</pre>
<p>Without Koenig lookup, namespaces impose an unacceptable tedium on the programmer,
who has to either repeatedly specify the fully qualified names or use numerous
<tt>using</tt> declarations. To push the argument in favor of Koenig lookup
even further, consider the following example:</p>
<pre>
<tt>#include<iostream></tt>
<tt>using std::cout;</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> cout<<"hello"; //OK, operator << is brought into scope by Koenig lookup</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<p>The <tt>using</tt> declaration injects <tt>std::cout</tt> into the scope of
<tt>main()</tt>, thereby enabling the programmer to use the nonqualified name
<tt>cout</tt>. However, the overloaded <tt><<</tt> operator, as you might
recall, is not a member of <tt>std::cout</tt>. It is a friend function that
is defined in namespace <tt>std</tt>, and which takes a <tt>std::ostream</tt>
object as its argument. Without Koenig lookup, the programmer has to write something
similar to the following:</p>
<pre>
<tt>std::operator<<(cout, "hello");</tt>
</pre>
<p>Alternatively, the programmer can provide a <tt>using namespace std;</tt> directive.
None of these options are desirable, however, because they clutter up code and
can become a source of confusion and errors. (<tt>using</tt> directives are
the least favorable form for rendering names visible in the current scope because
they make all the members of a namespace visible indiscriminately). Fortunately,
Koenig lookup "does the right thing" and saves you from this tedium in an elegant
way.</p>
<p>Koenig lookup is applied automatically. No special directives or configuration
switches are required to activate it, nor is there any way to turn it off. This
fact has to be kept in mind because it can have surprising results in some circumstances.
For example</p>
<pre>
<tt>namespace NS1</tt>
<tt>{</tt>
<tt> class B{};</tt>
<tt> void f;</tt>
<tt>};</tt>
<tt>void f(NS1::B); </tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> NS1::B b;</tt>
<tt> f; // ambiguous; NS1::f() or f(NS1::B)?</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<p>A Standard-compliant compiler should issue an error on ambiguity between <tt>NS1::f(NS1::B)</tt>
and <tt>f(NS1::B)</tt>. However, noncompliant compilers do not complain about
the ambiguous call; they simply pick one of the versions of <tt>f()</tt>. This,
however, might not be the version that the programmer intended. Furthermore,
the problem might arise only at a later stage of the development, when additional
versions of <tt>f()</tt> are added to the project -- which can stymie the compiler's
lookup algorithm. This ambiguity is not confined to global names. It might also
appear when two namespaces relate to one another -- for instance, if a namespace
declares classes that are used as parameters of a class member function that
is declared in a different namespace.</p>
<h3> <a name="Heading10">Namespaces in Practice</a></h3>
<p>The conclusion that can be drawn from the previous examples is that namespaces,
like other language features, must be used judiciously. For small programs that
contain only a handful of classes and a few source files, namespaces are not
necessary. In most cases, such programs are coded and maintained by a single
programmer, and they use a limited number of components. The likelihood of name
clashes in this case is rather small. If name clashes still occur, it is always
possible to rename the existing classes and functions, or simply to add namespace
later.</p>
<p>On the other hand, large-scale projects -- as was stated previously -- are
more susceptible to name clashes; therefore, they need to use namespaces systematically.
It is not unusual to find projects on which hundreds of programmers on a dozen
or so development teams are working together. The development of Microsoft Visual
C++ 6.0, for example, lasted 18 months, and more than 1000 people were involved
in the development process. Managing such a huge project requires well documented
coding policies -- and namespaces are one of the tools in the arsenal.</p>
<h2> <a name="Heading11">Namespace Utilization Policy in Large-Scale Projects</a></h2>
<p>To see how namespaces can be used in configuration management, imagine an online
transaction processing system of an imaginary international credit card company,
Unicard. The project comprises several development teams. One of them, the database
administration team, is responsible for the creation and maintenance of the
database tables, indexes, and access authorizations. The database team also
has to provide the access routines and data objects that retrieve and manipulate
the data in the database. A second team is responsible for the graphical user
interface. A third team deals with the international online requests that are
initiated by the cinemas, restaurants, shops, and so on where tourists pay with
their international Unicard. Every purchase of a cinema ticket, piece of jewelry,
or art book has to be confirmed by Unicard before the card owner is charged.
The confirmation process involves checking for the validity of the card, its
expiration date, and the card owner's balance. A similar confirmation procedure
is required for domestic purchases. However, international confirmation requests
are transmitted via satellite, whereas domestic confirmations are usually done
on the telephone. </p>
<p>In software projects, code reuse is paramount. Because the same business logic
is used for both domestic and international confirmations, the same database
access objects need to be used to retrieve the relevant information and perform
the necessary computations. Still, an international confirmation also involves
a sophisticated communication stack that receives the request that is transmitted
via satellite, decrypts it, and returns an encrypted response to the sender.
A typical implementation of satellite-based confirmation application can be
achieved by means of combining the database access objects with the necessary
communication objects that encapsulate protocols, communication layers, priority
management, message queuing, encryption, and decryption. It is not difficult
to imagine a name conflict resulting from the simultaneous use of the communication
components and the database access objects. </p>
<p>For example, two objects -- one encapsulating a database connection and the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -