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

📄 ch08.htm

📁 c++语言操作手册
💻 HTM
📖 第 1 页 / 共 3 页
字号:
  other referring to a satellite connection -- can have an identical name: <tt>Connection.</tt>   If, however, communication software components and database access objects are   declared in two distinct namespaces, the potential of name clashes is minimized.   Therefore, <tt>com::Connection</tt> and <tt>dba::Connection</tt> can be used   in the same application simultaneously. A systematic approach can be based on   allocating a separate namespace for every team in a project in which all the   components are declared. Such a policy can help you avoid name clashes among   different teams and third party code used in the project.</p><h2> <a name="Heading12">Namespaces and Version Control</a></h2><p>Successful software projects do not end with the product's rollout. In most   projects, new versions that are based on their predecessors are periodically   released. Moreover, previous versions have to be supported, patched, and adjusted   to operate with new operating systems, locales, and hardware. Web browsers,   commercial databases, word processors, and multimedia tools are examples of   such products. It is often the case that the same development team has to support   several versions of the same software product. A considerable amount of software   can be shared among different versions of the same product, but each version   also has its specific components. Namespace aliases can be used in these cases   to switch swiftly from one version to another.</p><p>Continuous projects in general have a pool of infrastructure software components   that are used ubiquitously. In addition, every version has its private pool   of specialized components. Namespace aliases can provide <i>dynamic namespaces</i>;   that is, a namespace alias can point at a given time to a namespace of version   X and, at another time, it can refer to a different namespace. For example</p><pre><tt>namespace ver_3_11  //16 bit</tt><tt>{  </tt><tt>  class Winsock{/*..*/};</tt><tt>  class FileSystem{/*..*/};</tt><tt>};</tt><tt>namespace ver_95 //32 bit</tt><tt>{  </tt><tt>  class Winsock{/*..*/};</tt><tt>  class FileSystem{/*..*/};</tt><tt>}</tt><tt>int main()//implementing 16 bit release</tt><tt>{ </tt><tt>  namespace current = ver_3_11; // current is an alias of ver_3_11</tt><tt>  using current::Winsock;</tt><tt>  using current::FileSystem;</tt><tt>  FileSystem  fs; // ver_3_11::FileSystem</tt><tt>  //...</tt><tt>  return 0;</tt><tt>}</tt></pre><p>In this example, the alias <tt>current</tt> is a symbol that can refer to either   <tt>ver_3_11</tt> or <tt>ver_95</tt>. To switch to a different version, the   programmer only has to assign a different namespace to it.</p><h3> <a name="Heading13">Namespaces Do not Incur Additional Overhead</a></h3><p>Namespace resolution, including Koenig lookup, are statically resolved. The   underlying implementation of namespaces occurs by means of <i>name mangling,</i>   whereby the compiler incorporates the function name with its list of arguments,   its class name, and its namespace in order to create a unique name for it (see   Chapter 13, "C Language Compatibility Issues," for a detailed account of name   mangling). Therefore, namespaces do not incur any runtime or memory overhead.</p><h2> <a name="Heading14">The Interaction of Namespaces with Other Language Features</a></h2><p>Namespaces interact with other features of the language and affect programming   techniques. Namespaces made some features in C++ superfluous or undesirable.</p><h3> <a name="Heading15">Scope Resolution Operator Should Not Be Used To Designate   Global Names</a></h3><p>In some frameworks (MFC, for instance), it is customary to add the scope resolution   operator, <tt>::</tt>, before a global function's name to mark it explicitly   as a function that is not a class member (as in the following example):</p><pre><tt>void String::operator = (const String&amp; other)</tt><tt>{</tt><tt>  ::strcpy (this-&gt;buffer, other.getBuff()); </tt><tt>}</tt></pre><p>This practice is not recommended. Many of the standard functions that were   once global are now grouped inside namespaces. For example, <tt>strcpy</tt>   now belongs to namespace <tt>std</tt>, as do most of the Standard Library's   functions. Preceding these functions with the scope resolution operator might   confuse the lookup algorithm of the compiler; furthermore, doing so undermines   the very idea of partitioning the global namespace. Therefore, it is recommended   that you leave the scope resolution operator off the function's name.</p><h3> <a name="Heading16">Turning an External Function into A File-Local Function</a></h3><p>In standard C, a nonlocal identifier that is declared to be static has <i>internal   linkage</i>, which means that it is accessible only from within the translation   unit (source file) in which it is declared (see also Chapter 2, "Standard Briefing:   The Latest Addenda to ANSI/ISO C++"). This technique is used to support information   hiding (as in the following example):</p><pre><tt>    //File hidden.c</tt><tt>static void decipher(FILE *f); // accessible only from within this file</tt><tt>    // now use this function in the current source file</tt><tt>decipher ("passwords.bin");</tt><tt>    //end of file</tt></pre><p>Although it is still supported in C++, this convention is now considered a   <i>deprecated feature. </i>Future releases of your compiler might issue a warning   message when they find a static identifier that is not a member of a class.   In order to make a function accessible only from within its translation unit,   use an <i>unnamed namespace </i>instead. The following example demonstrates   the process:</p><pre><tt>//File hidden.cpp</tt><tt>namespace        //unnamed</tt><tt>{</tt><tt>  void decipher(FILE *f);  // accessible only from within this file</tt><tt>}</tt><tt>  //now use the function in the current source file. </tt><tt>  //No using declarations or directives are needed</tt><tt>decipher ("passwords.bin");</tt></pre><p>Although names in an unnamed namespace might have external linkage, they can   never be seen from any other translation unit; the net effect of this is that   the names of an unnamed namespace appear to have static linkage. If you declare   another function with the same name in an unnamed namespace of another file,   the two functions are hidden from one another, and their names do not clash.</p><h3> <a name="Heading17">Standard Headers Names</a></h3><p>All Standard C++ header files now have to be included as follows:</p><pre><tt>#include &lt;iostream&gt; //note: no ".h" extension</tt></pre><p>That is, the .h extension is omitted. Standard C header files also obey this   convention, with the addition of the letter <i>c</i> to their name. Therefore,   a C standard header that was formerly named <tt>&lt;xxx.h&gt;</tt> is now <tt>&lt;cxxx&gt;</tt>.   For example</p><pre><tt>#include &lt;cassert&gt; //formerly: &lt;assert.h&gt;  note the prefix 'c' and the //omission of  ".h"</tt></pre><p>The older convention for C headers, <tt>&lt;xxx.h&gt;</tt>, is still supported;   however, it is now considered deprecated and, therefore, is not to not be used   in new C++ code. The reason for this is that C <tt>&lt;xxx.h&gt;</tt> headers   inject their declarations into the global namespace. In C++, however, most standard   declarations are grouped under namespace <tt>std</tt>,<i> </i>as are the <tt>&lt;cxxx&gt;</tt>   Standard C headers. No inference is to be drawn from the actual name convention   that is used on the physical location of a header file or its underlying name.   In fact, most implementations share a single physical file for the <tt>&lt;xxx.h&gt;</tt>   and its corresponding <tt>&lt;cxxx&gt;</tt> notation. This is feasible due to   some under-the-hood preprocessor tricks. Recall that you need to have a<i> </i><tt>using</tt>   declaration, a<i> </i><tt>using</tt> directive, or a fully qualified name in   order to access the declarations in the new style standard headers. For example</p><pre><tt>#include &lt;cstdio&gt;</tt><tt>using namespace std;  </tt><tt>void f()</tt><tt>{</tt><tt>    printf ("Hello World\n");</tt><tt>}</tt></pre><h2> <a name="Heading18">Restrictions on Namespaces</a></h2><p>The C++ Standard defines several restrictions on the use of namespaces. These   restrictions are meant to avert anomalies or ambiguities that can create havoc   in the language.</p><h3> <a name="Heading19">Namespace std Can Not Be Modified</a></h3><p>Generally, namespaces are open, so it is perfectly legal to expand existing   namespaces with additional declarations and definitions across several files.   The only exception to the rule is namespace <tt>std</tt>. According to the Standard,   the result of modifying namespace <tt>std</tt> with additional declarations   -- let alone the removal of existing ones -- yields undefined behavior, and   is to be avoided. This restriction might seem arbitrary, but it's just common   sense -- any attempt to tamper with namespace <tt>std</tt> undermines the very   concept of a namespace dedicated exclusively to standard declarations.</p><h3> <a name="Heading20">User-Defined new and delete Cannot Be Declared in a Namespace</a></h3><p>The Standard prohibits declarations of <tt>new</tt> and <tt>delete</tt> operators   in a namespace. To see why, consider the following example:</p><pre><tt>char *pc; //global</tt><tt>namespace A</tt><tt>{</tt><tt>  void* operator new ( std::size_t );</tt><tt>  void operator delete ( void * );</tt><tt>  void func ()</tt><tt>  {</tt><tt>    pc = new char ( 'a'); //using A::new</tt><tt>  }</tt><tt>} //A</tt><tt>void f() { delete pc; } // call A::delete or //::delete?</tt></pre><p>Some programmers might expect the operator <tt>A::delete</tt> to be selected   because it matches the operator <tt>new</tt> that was used to allocate the storage;   others might expect the standard operator <tt>delete</tt> to be called because   <tt>A::delete</tt> is not visible in function <tt>f()</tt>. By prohibiting declarations   of <tt>new</tt> and <tt>delete</tt> in a namespace altogether, C++ avoids any   such ambiguities.</p><h2> <a name="Heading21">Conclusions</a></h2><p>Namespaces were the latest addition to the C++ Standard. Therefore, some compilers   do not yet support this feature. However, all compiler vendors will incorporate   namespace support in the near future. The importance of namespaces cannot be   over-emphasized. As you have seen, any nontrivial C++ program utilizes components   of the Standard Template Library, the <tt>iostream</tt> library, and other standard   header files -- all of which are now namespace <tt>members</tt>.</p><p>Large-scale software projects can use namespaces cleverly to avoid common pitfalls   and to facilitate version control, as you have seen.</p><p>C++ offers three methods for injecting a namespace constituent into the current   scope. The first is a <tt>using</tt> directive, which renders all the members   of a namespace visible in the current scope. The second is a <tt>using</tt>   declaration, which is more selective and enables the injection of a single component   from a namespace. Finally, a fully qualified name uniquely identifies a namespace   member. In addition, the argument-dependent lookup, or Koenig lookup, captures   the programmer's intention without forcing him or her to use wearying references   to a namespace.</p><p> </p><CENTER><P><HR>  <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> <BR><BR><BR><p></P><P>&#169; <A HREF="/publishers/que/series/professional/0789720221/copy.htm">Copyright 1999</A>, Macmillan Computer Publishing. Allrights reserved.</p></CENTER></BODY></HTML>

⌨️ 快捷键说明

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