📄 index.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META NAME="Author" Content="Steph Mineart">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<TITLE>ANSI/ISO C++ Professional Programmer's Handbook - Chapter 8 - Namespaces</TITLE>
<link rel="stylesheet" TYPE="text/css" href="/includes/stylesheets/ebooks.css">
</head>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<CENTER>
<H1><img src="/publishers/que/series/professional/0789720221/button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
ANSI/ISO C++ Professional Programmer's Handbook</H1>
</CENTER>
<CENTER>
<P><A HREF="/publishers/que/series/professional/0789720221/index.htm"><img src="/publishers/que/series/professional/0789720221/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<H1 align="center">8</H1>
<h1 align="center"> Namespaces</h1>
<address>by Danny Kalev</address>
<ul>
<li><a href="#Heading1">The Rationale Behind Namespaces</a>
<li><a href="#Heading2">A Brief Historical Background</a>
<ul>
<li><a href="#Heading3">Large-Scale Projects Are More Susceptible to Name
Clashes</a>
</ul>
<li><a href="#Heading4">Properties of Namespaces</a>
<ul>
<li><a href="#Heading5">Fully Qualified Names</a>
<li><a href="#Heading6">A using Declaration and a using Directive</a>
<li><a href="#Heading7">Namespaces Can Be Extended </a>
<li><a href="#Heading8">Namespace Aliases</a>
<li><a href="#Heading9">Koenig Lookup</a>
<li><a href="#Heading10">Namespaces in Practice</a>
</ul>
<li><a href="#Heading11">Namespace Utilization Policy in Large-Scale Projects</a>
<li><a href="#Heading12">Namespaces and Version Control</a>
<ul>
<li><a href="#Heading13">Namespaces Do not Incur Additional Overhead</a>
</ul>
<li><a href="#Heading14">The Interaction of Namespaces with Other Language Features</a>
<ul>
<li><a href="#Heading15">Scope Resolution Operator Should Not Be Used To
Designate Global Names</a>
<li><a href="#Heading16">Turning an External Function into A File-Local
Function</a>
<li><a href="#Heading17">Standard Headers Names</a>
</ul>
<li><a href="#Heading18">Restrictions on Namespaces</a>
<ul>
<li><a href="#Heading19">Namespace std Can Not Be Modified</a>
<li><a href="#Heading20">User-Defined new and delete Cannot Be Declared
in a Namespace</a>
</ul>
<li><a href="#Heading21">Conclusions</a>
</ul>
<hr size=4>
<p>Namespaces were introduced to the C++ Standard in 1995. This chapter explains
what namespaces are and why they were added to the language. You will see how
namespaces can avoid name conflicts and how they facilitate configuration management
and version control in large-scale projects. Finally, you will learn how namespaces
interact with other language features.</p>
<h2> <a name="Heading1">The Rationale Behind Namespaces</a></h2>
<p>In order to understand why namespaces were added to the language in the first
place, here's an analogy: Imagine that the file system on your computer did
not have directories and subdirectories at all. All files would be stored in
a flat repository, visible all the time to every user and application. Consequently,
extreme difficulties would arise: Filenames would clash (with some systems limiting
a filename to eight characters, plus three for the extension, this is even more
likely to happen), and simple actions such as listing, copying, or searching
files would be much more difficult. In addition, security and authorization
restrictions would be severely compromised.</p>
<p>Namespaces in C++ are equivalent to directories. They can be nested easily,
they protect your code from name conflicts, they enable you to hide declarations,
and they do not incur any runtime or memory overhead. Most of the components
of the C++ Standard Library are grouped under namespace <tt>std</tt>. Namespace
<tt>std</tt> is subdivided into additional namespaces such as <tt>std::rel_ops</tt>,
which contains the definitions of STL's overloaded operators.</p>
<h2> <a name="Heading2">A Brief Historical Background</a></h2>
<p>In the early 1990s, when C++ was gaining popularity as a general purpose programming
language, many vendors were shipping proprietary implementations of various
component classes. Class libraries for string manipulations, mathematical functions,
and data containers were integral parts of frameworks such as MFC, STL, OWL,
and others. The proliferation of reusable components caused a name-clashing
problem. A class named <tt>vector</tt><i>, </i>for instance, might appear in
a mathematical library and in another container library that were both used
at the same time; or a class named <tt>string</tt> might be found in almost
every framework and class library. It was impossible for the compiler to distinguish
between different classes that had identical names. Similarly, linkers could
not cope with identical names of member functions of classes with indistinguishable
names. For example, a member function</p>
<pre>
<tt>vector::operator==(const vector&);</tt>
</pre>
<p>might be defined in two different classes -- the first might be a class of
a mathematical library, whereas the other might belong to some container library.</p>
<h3> <a name="Heading3">Large-Scale Projects Are More Susceptible to Name Clashes</a></h3>
<p>Name-clashes are not confined to third party software libraries. In large-scale
software projects, short and elegant names for classes, functions, and constants
can also cause name conflicts because it is likely that the same name might
be used more than once to indicate different entities by different developers.
In the pre-namespace era, the only workaround was to use various affixes in
identifiers' names. This practice, however, is tedious and error prone. Consider
the following:</p>
<pre>
<tt>class string // short but dangerous. someone else may have picked //this name already...</tt>
<tt>{</tt>
<tt> //...</tt>
<tt>};</tt>
<tt>class excelSoftCompany_string // a long name is safer but tedious. //A nightmare if company changes its name...</tt>
<tt>{</tt>
<tt> //...</tt>
<tt>}; </tt>
</pre>
<p>Namespaces enable you to use convenient, short, and intelligible names safely.
Instead of repeating the unwieldy affixes time after time, you can group your
declarations in a namespace and factor out the recurring affix as follows:</p>
<pre>
<tt>//file excelSoftCompany.h</tt>
<tt>namespace excelSoftCompany { // a namespace definition</tt>
<tt> class string {/*..*/};</tt>
<tt> class vector {/*..*/};</tt>
<tt>}</tt>
</pre>
<p>Namespace members, like class members, can be defined separately from their
declarations. For example</p>
<pre>
<tt>#include <iostream></tt>
<tt>using namespace std;</tt>
<tt>namespace A</tt>
<tt>{</tt>
<tt> void f(); //declaration</tt>
<tt>}</tt>
<tt>void A::f() //definition in a separate file</tt>
<tt>{</tt>
<tt> cout<<"in f"<<endl;</tt>
<tt>}</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> A::f();</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<h2> <a name="Heading4">Properties of Namespaces</a></h2>
<p>Namespaces are more than just name containers. They were designed to allow
fast and simple migration of legacy code without inflicting any overhead. Namespaces
have several properties that facilitate their usage. The following sections
discuss these properties.</p>
<h3> <a name="Heading5">Fully Qualified Names</a></h3>
<p>A namespace is a scope in which declarations and definitions are grouped together.
In order to refer to any of these from another scope, a <i>fully qualified name</i>
is required. A fully qualified name of an identifier consists of its namespaces,
followed by a scope resolution operator (<tt>::</tt>), its class name, and,
finally, the identifier itself. Because both namespaces and classes can be nested,
the resulting name can be rather long -- but it ensures unique identification:</p>
<pre>
<tt>unsigned int maxPossibleLength =</tt>
<tt> std::string::npos; //a fully qualified name. npos is a member of string; //string belongs to namespace std</tt>
<tt> int *p = ::new int; //distinguish global new from overloaded new </tt>
</pre>
<p>However, repeating the fully qualified name is tedious and less readable. Instead,
you can use a<i> using declaration</i> or a <i>using directive</i>.</p>
<h3> <a name="Heading6">A using Declaration and a using Directive</a></h3>
<p>A <tt>using</tt> declaration consists of the keyword <tt>using</tt>, followed
by a <cite>namespace::member</cite>. It instructs the compiler to locate every
occurrence of a certain identifier (type, operator, function, constant, and
so on) in the specified namespace, as if the fully qualified name were supplied.
For example</p>
<pre>
<tt>#include <vector> //STL vector; defined in namespace std</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> using std::vector; //using declaration; every occurrence of vector //is looked up in std</tt>
<tt> vector <int> vi; </tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<p>A <tt>using</tt> directive, on the other hand, renders all the names of a specified
namespace accessible in the scope of the directive. It consists of the following
sequence: <tt>using namespace</tt>, followed by a namespace name. For example</p>
<pre>
<tt>#include <vector> // belongs to namespace std</tt>
<tt>#include <iostream> //iostream classes and operators are also in namespace std</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt> using namespace std; // a using-directive; all <iostream> and <vector> //declarations now accessible</tt>
<tt> vector <int> vi;</tt>
<tt> vi.push_back(10);</tt>
<tt> cout<<vi[0];</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<p>Look back at the <tt>string</tt> class example (the code is repeated here for
convenience):</p>
<pre>
<tt>//file excelSoftCompany.h</tt>
<tt>namespace excelSoftCompany </tt>
<tt>{ </tt>
<tt> class string {/*..*/};</tt>
<tt> class vector {/*..*/};</tt>
<tt>}</tt>
</pre>
<p>You can now access your own <tt>string</tt> class as well as the standard <tt>string</tt>
class in the same program as follows:</p>
<pre>
<tt>#include <string> // std::string</tt>
<tt>#include "excelSoftCompany.h"</tt>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -