- 浏览: 918746 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
yaawaas:
有了 。。
程序员装B指南 -
niepeng880208:
藐视我还是初级装
程序员装B指南 -
sa364867195:
哥们,现在实现了吗?
GPS卫星定位车辆监控系统 -
月下小人:
顶,这才是质的提高,果断顶
一个基于jQuery ajax和.net httphandler 的超轻异步框架,千行代码完成。 -
xp9802:
有意思,动静结合
程序员装B指南
Felomeng翻译:Google C++ 编程规范——作用域收藏 function change_alt1(btn,style){var btn=document.getElementById(btn);btn.style.display = style;}此文于2011-03-24被推荐到CSDN首页如何被推荐?
<p class="Heading1ForEnglish" style=""><span style="color: #ff0000;">与官方翻译版本(<a href="http://code.google.com/p/zh-google-styleguide/downloads/list">http://code.google.com/p/zh-google-styleguide/downloads/list</a>)不同,本文为本人原创翻译。</span></p>
<p class="Heading1ForEnglish" style=""><a name="_Toc288281537"><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: x-large;">1</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style=""><span style="font-size: x-large;">作用域</span></span></a></p>
<p class="Heading2ForEnglish" style=""><a name="%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"></a><a name="_Toc288281538"><span style=""><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.1</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><span style=""><strong><span style="font-size: large;">命名空间</span></strong></span></span></a><strong><span style="font-size: large;"><span style="">(</span><span lang="EN-US"><span style="font-family: Cambria;">namespace</span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">中提倡使用匿名命名空间(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">unnamed namespace</span><a style="" name="_ednref1" href="#_edn1"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[i]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">)。而定名命名空间(</span><span lang="EN-US"><span style="font-family: Times New Roman;">named namespace</span></span><span style="">)的命名应该以项目及(如果不在根目录的话)项目中的路径来命名。不要使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">关键字。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">定义:</span></strong><span style="">命名空间将作用域分割为相互独立的,具有特定名称的作用域。这样就可以避免在全局作用域中容易产生的同名冲突。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">在类提供的(有层次的)名称隔离方法基础上提供了另一套(有层次的)命名隔离方法</span></span><a style="" name="_ednref2" href="#_edn2"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[ii]</span></span></span></span></span></span></a><span style="font-size: small;"><span style="">。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">例如,两个不同的工程中都含有全局类</span><span style="" lang="EN-US">Foo</span><span style="">,这两个类名可能在编译时或者运行时产生同名冲突。但是,如果在每个工程中都将他们放进相应的命名空间中,</span><span style="" lang="EN-US">project1::Foo</span><span style="">和</span><span style="" lang="EN-US">project2::Foo</span><span style="">就是两个完全不同的类名,而不会再产生同名冲突了。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">命名空间容易让人感到迷惑,因为类本身已经提供了一套(有层次的)名称隔离方法,而命名空间在这个基础上又添加了一套(有层次的)名称隔离方法。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在头文件中使用匿名命名空间,很容易违反</span><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">的单一定义规则(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">One Definition Rule</span><a style="" name="_ednref3" href="#_edn3"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iii]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">)。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">根据下述原则使用命名空间。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><strong style=""><span style="font-size: small;"><span style="">匿名命名空间</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件中,不仅允许使用匿名命名空间,并且,为了避免运行时同名冲突,还提倡使用匿名命名空间:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 9.05pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace {<span style=""> </span>// This is in a .cc file.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// The content of a namespace is not indented</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">enum { kUnused, kEOF, kError };<span style=""> </span>// Commonly used tokens.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">bool AtEof() { return pos_ == kEOF; }<span style=""> </span>// Uses our namespace's EOF.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 27pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">但是,文件内的与某个特定类相关的实体,应当在该类内声明为类型、静态成员或静态成员函数,而不是在类外声明为匿名命名空间的一个成员。如上例所示,在匿名空间的结尾处要添加注释“</span><span style="" lang="EN-US">// namespace</span><span style="">”。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.h</span><span style="">文件中不要使用匿名命名空间。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><strong style=""><span style="font-size: small;"><span style="">定名命名空间</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">定名命名空间用法如下:</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style=""><span style="font-size: small;">除文件最前端的包含语句、</span></span><span lang="EN-US"><a href="http://google-gflags.googlecode.com/"><span style="color: blue;"><span style="font-family: Times New Roman; font-size: small;">gflags</span></span></a><a style="" name="_ednref4" href="#_edn4"><span class="MsoEndnoteReference"><span style="text-decoration: underline;"><span style="color: blue;"><span style=""><span class="MsoEndnoteReference"><span style="text-decoration: underline;"><span style="" lang="EN-US">[iv]</span></span></span></span></span></span></span></a></span><span style="font-size: small;"><span style="">定义(声明)以及前置声明的别的命名空间中的类之外,命名空间包含整个源代码文件的内容:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// In the .h file</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace mynamespace {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// All declarations are within the namespace scope.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Notice the lack of indentation.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">class MyClass {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>public:</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>...</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>void Foo();</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">};</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace mynamespace</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">// In the .cc file</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace mynamespace {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">// Definition of functions is within scope of the namespace.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">void MyClass::Foo() {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>...</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace mynamespace</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">典型的</span><span style="" lang="EN-US">.cc</span><span style="">文件可能会非常复杂,还有可能引用到别的命名空间中的类。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">#include "a.h"</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">DEFINE_bool(someflag, false, "dummy flag");</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">class C;<span style=""> </span>// Forward declaration of class C in the global namespace.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace a { class A; }<span style=""> </span>// Forward declaration of a::A.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace b {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">...code for b...<span style=""> </span><span style=""></span>// Code goes against the left margin.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace b</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">不要在</span><span style="" lang="EN-US">std</span><span style="">命名空间内定义声明内容,包括标准库中类的前置声明。在命名空间中声明任何实体都是未定义行为(</span></span><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">undefined behavior<span class="MsoFootnoteReference"> </span></span></span><a style="" name="_ednref5" href="#_edn5"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[v]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">),就是说不可移植。声明标准库中实体的方法是包含相应的头文件。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">没有必要使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句让命名空间内所有的实体名都可用。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; margin-left: 3.3pt; border-top: #fff0f0 1pt solid; margin-right: 0cm; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #cc0000; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Forbidden -- This pollutes the namespace.</span></p>
</div>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; margin-left: 21.3pt; border-top: #fff0f0 1pt solid; margin-right: 0cm; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">using namespace foo;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件中的任何位置都可以使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句,在</span><span style="" lang="EN-US">.h</span><span style="">文件中的函数、方法和类内可以使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// OK in .cc files.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Must be in a function, method or class in .h files.</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">using ::foo::bar;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件内的任何地方,包含整体文件的定名命名实体内的任何地方,以及函数和方法内部都可以使用命名实体别名(</span><span lang="EN-US"><span style="font-family: Times New Roman;">namespace aliases</span></span><span style="">)。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Shorten access to some commonly used names in .cc files.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace fbz = ::foo::bar::baz;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Shorten access to some commonly used names (in a .h file).</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace librarian {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// The following alias is available to all files including</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// this header (in namespace librarian):</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// alias names should therefore be chosen consistently</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// within a project.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace pd_s = ::pipeline_diagnostics::sidetable;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">inline void my_inline_function() {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>// namespace alias local to a function (or method).</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>namespace fbz = ::foo::bar::baz;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>...</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">}</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">} <span style=""></span>// namespace librarian</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">注意,在头文件中定义的别名,在任何包含这个头文件的文件中都是可见的。所以在公共头文件中(这些头文件可以在工程外被包含),以及间接地被这些公共头文件包含的头文件中,应当避免使用别名。这也是保持</span><span lang="EN-US"><span style="font-family: Times New Roman;">API</span></span><span style="">尽量简洁总目标的一部分。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281539"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.2</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">内嵌类(</span><span lang="EN-US"><span style="font-family: Cambria;">Nested Class</span></span></span></strong></a><strong><span style="font-size: large;"><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">虽然,当内嵌类是接口的一部分时,可以声明为</span><span lang="EN-US"><span style="font-family: Times New Roman;">public</span></span><span style="">,但最好还是使用命名空间将内嵌类声明与全局作用域隔离。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">定义:</span></strong><span style="">在类内部定义的另一个类;这个内部的类也称为成员类(</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">member class</span></span></em><span style="">)。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">class Foo {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""></span>private:</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>// Bar is a member class, nested within Foo.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>class Bar {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>...</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>};</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">};</span></p>
</div>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">当只有内嵌类的外层类(</span><span lang="EN-US"><span style="font-family: Times New Roman;">enclosing class</span></span><span style="">)使用它时很有用,这时可以将它定义为外层类的成员,从而把它的作用域限定在外层类的内部,避免声明在外部作用域所带来的名称污染(即不会影响到用不到其他的类)。内嵌类可以在外层类中前置声明,然后在</span><span style="" lang="EN-US">.cc</span><span style="">文件中定义。这样一来,就可以避免在外层类的定义中定义整个内嵌类,而且内嵌类一般也只与实现相关。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">内嵌类只能在外层类的定义内前置声明。所以,任何使用</span><span style="" lang="EN-US">Foo::Bar*</span><span style="">指针的头文件都需要包含</span><span style="" lang="EN-US">Foo</span><span style="">类的完整声明。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">除非内嵌类是接口的一部分,否则不要声明为</span><span lang="EN-US"><span style="font-family: Times New Roman;">public</span></span><span style="">的,例如,一个类包含某方法的多个选项。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281540"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.3</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">非成员函数(</span><span lang="EN-US"><span style="font-family: Cambria;">Nonmember</span></span></span></strong></a><strong><span style="font-size: large;"><span style=""><span style="">)、静态成员函数(</span><span lang="EN-US"><span style="font-family: Cambria;"> Static Member</span></span></span><span style=""><span style="">)、全局函数(</span><span lang="EN-US"><span style="font-family: Cambria;">Global Functions</span></span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">优先使用命名空间内的非成员函数或静态成员函数,尽量不要使用全局函数。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">有时,非成员函数和静态成员函数很有用。将非成员函数放在某命名空间内,可以防止其对全局命名空间的名称污染。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">将非成员函数和静态函数作为一个新类的成员函数可能更合理,尤其当这些函数访问大量外部资源或具有大量依赖时。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">有时,定义一个类外函数是有用的,甚至是必须的。这样的函数可以是一个静态成员函数或者非成员函数。非成员函数不应依赖外部变量,并且应当总是只存在于一个命名空间内。不要用类把不含共享静态数据的静态成员函数封装起来,把这样的函数放到</span><span lang="EN-US"><a href="#%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"><span style="" lang="EN-US"><span lang="EN-US"><span style="color: #0000ff;">命<span lang="EN-US">名<span lang="EN-US">空间</span></span></span></span></span></a></span><span style="">中</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">和其他类在同一编译单元内定义的函数,如果在别的编译单元中直接调用,可能会引起额外的耦合和连接依赖,静态成员函数尤其明显。这时,应当考虑建立一个新类来封装这些函数,也可以将这些函数封装到独立类库的</span><span lang="EN-US"><a href="#%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"><span style="" lang="EN-US"><span lang="EN-US"><span style="color: #0000ff;">命名<span lang="EN-US">空间</span></span></span></span></a></span><span style="">中。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">如果必须定义一个非成员函数,并且只在当前</span><span style="" lang="EN-US">.cc</span><span style="">文件中使用,使用匿名命名空间或者</span><span style="" lang="EN-US">static</span><span style="">连接关键字(比如</span><span style="" lang="EN-US">static int Foo() {...}</span><span style="">)来限定它的作用域。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281541"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.4</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">局部变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Local Variable</span></span></span></strong></a><strong><span style="font-size: large;"><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">将函数中的变量作用域限定在尽量小的范围内,并且在定义时就初始化。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">允许在函数内任何地方声明变量。但是,要在尽量小的作用域中声明变量,最好在第一次使用前声明。这样,读代码的人就很容易找到定义,从而知道这个变量是什么类型,初始值是多少。这里要特别强调:定义和初始化应放在同一语句,而不是先定义后再单独进行赋值。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; border-top: #fff0f0 1pt solid; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">int i;</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">i = f();<span style=""> </span>// Bad -- initialization separate from declaration.</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">int j = g();<span style=""> </span>// Good -- declaration has initialization.</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">值得注意的是,</span><span lang="EN-US"><span style="font-family: Times New Roman;">gcc</span></span><span style="">中对</span><span style="" lang="EN-US">for (int i = 0; i < 10; ++i)</span><span style="">语句的实现是正确的(变量</span><span style="" lang="EN-US">i</span><span style="">的作用域限定在</span><span style="" lang="EN-US">for</span><span style="">循环内)。因此,在与这个</span><span style="" lang="EN-US">for</span><span style="">循环处于同一作用域中的其他</span><span style="" lang="EN-US">for</span><span style="">循环中还可以使用变量</span><span style="" lang="EN-US">i</span><span style="">。</span><span lang="EN-US"><span style="font-family: Times New Roman;">gcc</span></span><span style="">对</span><span style="" lang="EN-US">if</span><span style="">语句和</span><span style="" lang="EN-US">while</span><span style="">语句中声明的变量的作用域的实现也是正确的。比如:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">while (const char* p = strchr(str, '/')) str = p + 1;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">警告:如果变量是一个对象,那么在每次进入作用域时都调用构造函数并创建这个对象,而在出了作用域之后又会调用析构函数来销毁这个对象。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; border-top: #fff0f0 1pt solid; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">// Inefficient implementation:</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">for (int i = 0; i < 1000000; ++i) {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>Foo f;<span style=""> </span>// My ctor and dtor get called 1000000 times each.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>f.DoSomething(i);</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">可以将这样的变量声明在循环体外来提高效率。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">Foo f;<span style=""> </span>// My ctor and dtor get called once each.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">for (int i = 0; i < 1000000; ++i) {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>f.DoSomething(i);</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
</div>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281542"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.5</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">静态变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Static Variable</span></span></span></strong></a><strong><span style="font-size: large;"><span style=""><span style="">)和全局变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Global Variable</span></span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">禁止使用静态或全局的类类型变量:它们会引起不易找到的</span><span lang="EN-US"><span style="font-family: Times New Roman;">bug</span></span><span style="">,因为它们的构造和析构的顺序是不固定的。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style=""><span style="font-size: small;">对象如果存储在内存中的静态区(包括全局变量、静态变量、静态类成员变量和函数内部静态变量),必须是简单旧式数据(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">Plain Old Data</span><a style="" name="_ednref6" href="#_edn6"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vi]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">),即整型、字符型、单精度型或者简单旧式数据类型的指针、数组、结构体。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">但是,</span><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">中并未明确规定静态变量的构造函数和析构函数的调用顺序,甚至每次编译生成后的调用顺序可能都是不一样的。这样就可能导致不易发现的</span><span lang="EN-US"><span style="font-family: Times New Roman;">bug</span></span><span style="">。因此,不但禁止将类类型作为全局变量,还禁止使用函数返回值对静态简单旧式数据变量进行初始化,除非这个函数(如</span><span lang="EN-US"><span style="font-family: Times New Roman;">getenv()</span></span><span style="">,或</span><span lang="EN-US"><span style="font-family: Times New Roman;">getpid()</span></span><span style="">)本身并不依赖于其他的全局变量。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">按规定,析构函数的调用顺序与构造函数的调用顺序应当是正好相反的。因为构造函数的调用顺序是不确定的,所以析构函数的调用顺序也是不确定的。例如:在程序运行过程中,一个静态变量已经被销毁了,但是程序依然在运行,也许正好有另外一个线程试图去使用这个变量,这当然会失败。抑或是在调用某“</span><span lang="EN-US"><span style="font-family: Times New Roman;">string</span></span><span style="">”类型静态变量析构函数后,才去调用另一个变量的析构函数,而这个变量内包含有对此</span><span lang="EN-US"><span style="font-family: Times New Roman;">string</span></span><span style="">的引用。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">因此,规定静态变量只能是简单旧式数据类型。这条规则明确禁止把</span><span style="" lang="EN-US">vector</span><span lang="EN-US"><span style="font-family: Times New Roman;"> </span></span><span style="">(可以使用</span><span lang="EN-US"><span style="font-family: Times New Roman;">C</span></span><span style="">语言中的数组代替)和</span><span style="" lang="EN-US">string</span><span lang="EN-US"><span style="font-family: Times New Roman;"> </span></span><span style="">(可以使用</span><span style="" lang="EN-US">const char []</span><span style="">)声明为静态。</span></span></p>
<p><span style="">如果需要使用静态的或全局的类类型变量,那么请在</span><span style="" lang="EN-US">main</span><span style="">函数或</span><span style="" lang="EN-US">pthread_once</span><span style="">函数中初始化为一个指针(这个指针将不会被释放)。注意,这个指针必须是裸指针(</span><span style="" lang="EN-US">raw pointer<a style="" name="_ednref7" href="#_edn7"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vii]</span></span></span></span></span></a></span><span style="">),而不能是智能指针(</span><span style="" lang="EN-US">smart pointer</span><span style="">),因为智能指针的析构函数也有上文讨论过的调用顺序问题。</span><span style="font-family: Times New Roman; font-size: small;"> </span></p>
<div style="">
<br><span style="font-family: Times New Roman; font-size: small;">
<hr size="1"></span>
<div id="edn1" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn1" href="#_ednref1"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[i]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">unnamed namespace</span></span><span style="">原意为未命名的命名空间。在</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">中,命名空间分为命名的命名空间和未命名的命名空间。实际上,未命名的命名空间在编译时,编译器也会为它分配一个自动生成的唯一名称,以与其他的命名空间相区分。故这里译为匿名命名空间(不是没有名,而是人看不到它的名字)。与此对应,</span><span lang="EN-US"><span style="font-family: Calibri;">named namespace</span></span><span style="">译为定名命名空间。</span></span></p>
</div>
<div id="edn2" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn2" href="#_ednref2"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[ii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:这里读者需要对</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">的历史有一些了解。</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">是由</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="">语言进化来的。在</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="">语言中,所有的方法、函数以及变量等都是全局作用域命名的。但是随着软件工程规模的扩大,人们发现这样很不利于管理(很容易产生同名冲突)。于是有人提出了类的概念(当然,这只是类概念产生的众多原因中的一个)。这样每个类中有自己的方法、函数和变量,与其他类中(以及全局)的相应内容相互区分。故,类与命名空间的共同点就是对方法、函数和变量等名称的隔离(当然,命名空间还可以用来隔离类名)。</span></span></p>
</div>
<div id="edn3" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn3" href="#_ednref3"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">One Definition Rule </span></span><span style="">(缩写:</span><span lang="EN-US"><span style="font-family: Calibri;">ODR</span></span><span style="">)定义为:</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: small;">1.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">任何</span><span style="">编译单元中,模板、类型、函数、对象等最多都只能有一次定义。</span><span style="">当然,它们中有的可以在多处声明。定义就是构造一个实例。</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: small;">2.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">在整个程序中,一个对象或内联函数,只能有一处定义。如果使用了某对象或函数,那么这个对象或函数就必须得有唯一的定义。可以声明一个对象或函数,但却不使用它,这时不需要对它进行定义。任何情况下,都不能有多于一次的定义。</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN"><span style=""><span style="font-family: Calibri; font-size: small;">3.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">有些内容,如类型、模板、外部内联函数(</span><span lang="EN-US"><span style="font-family: Calibri;">extern</span></span><span style="">关键字修饰的内联函数),可以在多个编译单元中定义。对于一个给定的实体,所有的定义必须一致。不同编译单元中,同名且同类型(同参数)的非外部对象和函数是不同的实体。</span></span></p>
</div>
<div id="edn4" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn4" href="#_ednref4"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iv]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">gflags</span></span><span style="">是一个库文件包,主要用来处理命令行中的标识。从这点上讲,它可以替代</span><span lang="EN-US"><span style="font-family: Calibri;">getopt()</span></span><span style="">函数。不同的是,它更具灵活性。不仅支持</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">的类型(如</span><span lang="EN-US"><span style="font-family: Calibri;">string</span></span><span style="">),还可以在使用标识的源代码文件中定义新的标识。</span></span></p>
</div>
<div id="edn5" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn5" href="#_ednref5"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[v]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">undefined behavior</span></span><span style="">是指在</span><span lang="EN-US"><span style="font-family: Calibri;">C/C++</span></span><span style="">中,为了提高实现编译器的灵活性,对某些特定行为,在语言的标准中并没有规定他们的具体表现。所以,不同的编译器中,这些行为的表现可能是不同的。也是下面说不可移植的原因。</span></span></p>
</div>
<div id="edn6" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn6" href="#_ednref6"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vi]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">Plain Old Data</span></span><span style="">,是未经包装,且不含任何面向对象特性的变量类型构成的数据结构。</span></span></p>
</div>
<div id="edn7" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn7" href="#_ednref7"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">raw pointer</span></span><span style="">,即普通指针,与智能指针概念相对应。我们知识,智能指针是经过封装的指针,所以普通指针被译为裸指针。</span></span></p>
</div>
</div>
<p class="Heading1ForEnglish" style=""><a name="_Toc288281537"><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: x-large;">1</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style=""><span style="font-size: x-large;">作用域</span></span></a></p>
<p class="Heading2ForEnglish" style=""><a name="%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"></a><a name="_Toc288281538"><span style=""><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.1</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><span style=""><strong><span style="font-size: large;">命名空间</span></strong></span></span></a><strong><span style="font-size: large;"><span style="">(</span><span lang="EN-US"><span style="font-family: Cambria;">namespace</span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">中提倡使用匿名命名空间(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">unnamed namespace</span><a style="" name="_ednref1" href="#_edn1"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[i]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">)。而定名命名空间(</span><span lang="EN-US"><span style="font-family: Times New Roman;">named namespace</span></span><span style="">)的命名应该以项目及(如果不在根目录的话)项目中的路径来命名。不要使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">关键字。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">定义:</span></strong><span style="">命名空间将作用域分割为相互独立的,具有特定名称的作用域。这样就可以避免在全局作用域中容易产生的同名冲突。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">在类提供的(有层次的)名称隔离方法基础上提供了另一套(有层次的)命名隔离方法</span></span><a style="" name="_ednref2" href="#_edn2"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[ii]</span></span></span></span></span></span></a><span style="font-size: small;"><span style="">。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">例如,两个不同的工程中都含有全局类</span><span style="" lang="EN-US">Foo</span><span style="">,这两个类名可能在编译时或者运行时产生同名冲突。但是,如果在每个工程中都将他们放进相应的命名空间中,</span><span style="" lang="EN-US">project1::Foo</span><span style="">和</span><span style="" lang="EN-US">project2::Foo</span><span style="">就是两个完全不同的类名,而不会再产生同名冲突了。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">命名空间容易让人感到迷惑,因为类本身已经提供了一套(有层次的)名称隔离方法,而命名空间在这个基础上又添加了一套(有层次的)名称隔离方法。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在头文件中使用匿名命名空间,很容易违反</span><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">的单一定义规则(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">One Definition Rule</span><a style="" name="_ednref3" href="#_edn3"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iii]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">)。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">根据下述原则使用命名空间。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><strong style=""><span style="font-size: small;"><span style="">匿名命名空间</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件中,不仅允许使用匿名命名空间,并且,为了避免运行时同名冲突,还提倡使用匿名命名空间:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 9.05pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace {<span style=""> </span>// This is in a .cc file.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// The content of a namespace is not indented</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">enum { kUnused, kEOF, kError };<span style=""> </span>// Commonly used tokens.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">bool AtEof() { return pos_ == kEOF; }<span style=""> </span>// Uses our namespace's EOF.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 27pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">但是,文件内的与某个特定类相关的实体,应当在该类内声明为类型、静态成员或静态成员函数,而不是在类外声明为匿名命名空间的一个成员。如上例所示,在匿名空间的结尾处要添加注释“</span><span style="" lang="EN-US">// namespace</span><span style="">”。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.h</span><span style="">文件中不要使用匿名命名空间。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><strong style=""><span style="font-size: small;"><span style="">定名命名空间</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">定名命名空间用法如下:</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style=""><span style="font-size: small;">除文件最前端的包含语句、</span></span><span lang="EN-US"><a href="http://google-gflags.googlecode.com/"><span style="color: blue;"><span style="font-family: Times New Roman; font-size: small;">gflags</span></span></a><a style="" name="_ednref4" href="#_edn4"><span class="MsoEndnoteReference"><span style="text-decoration: underline;"><span style="color: blue;"><span style=""><span class="MsoEndnoteReference"><span style="text-decoration: underline;"><span style="" lang="EN-US">[iv]</span></span></span></span></span></span></span></a></span><span style="font-size: small;"><span style="">定义(声明)以及前置声明的别的命名空间中的类之外,命名空间包含整个源代码文件的内容:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// In the .h file</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace mynamespace {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// All declarations are within the namespace scope.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Notice the lack of indentation.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">class MyClass {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>public:</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>...</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>void Foo();</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">};</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace mynamespace</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">// In the .cc file</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace mynamespace {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">// Definition of functions is within scope of the namespace.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">void MyClass::Foo() {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>...</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace mynamespace</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">典型的</span><span style="" lang="EN-US">.cc</span><span style="">文件可能会非常复杂,还有可能引用到别的命名空间中的类。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">#include "a.h"</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">DEFINE_bool(someflag, false, "dummy flag");</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">class C;<span style=""> </span>// Forward declaration of class C in the global namespace.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace a { class A; }<span style=""> </span>// Forward declaration of a::A.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">namespace b {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">...code for b...<span style=""> </span><span style=""></span>// Code goes against the left margin.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}<span style=""> </span>// namespace b</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">不要在</span><span style="" lang="EN-US">std</span><span style="">命名空间内定义声明内容,包括标准库中类的前置声明。在命名空间中声明任何实体都是未定义行为(</span></span><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">undefined behavior<span class="MsoFootnoteReference"> </span></span></span><a style="" name="_ednref5" href="#_edn5"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[v]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">),就是说不可移植。声明标准库中实体的方法是包含相应的头文件。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">没有必要使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句让命名空间内所有的实体名都可用。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; margin-left: 3.3pt; border-top: #fff0f0 1pt solid; margin-right: 0cm; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #cc0000; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Forbidden -- This pollutes the namespace.</span></p>
</div>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; margin-left: 21.3pt; border-top: #fff0f0 1pt solid; margin-right: 0cm; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">using namespace foo;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件中的任何位置都可以使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句,在</span><span style="" lang="EN-US">.h</span><span style="">文件中的函数、方法和类内可以使用</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">using</span></span></em><span style="">语句。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// OK in .cc files.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Must be in a function, method or class in .h files.</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">using ::foo::bar;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">在</span><span style="" lang="EN-US">.cc</span><span style="">文件内的任何地方,包含整体文件的定名命名实体内的任何地方,以及函数和方法内部都可以使用命名实体别名(</span><span lang="EN-US"><span style="font-family: Times New Roman;">namespace aliases</span></span><span style="">)。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 3.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Shorten access to some commonly used names in .cc files.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace fbz = ::foo::bar::baz;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// Shorten access to some commonly used names (in a .h file).</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace librarian {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// The following alias is available to all files including</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// this header (in namespace librarian):</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// alias names should therefore be chosen consistently</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">// within a project.</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">namespace pd_s = ::pipeline_diagnostics::sidetable;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">inline void my_inline_function() {</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>// namespace alias local to a function (or method).</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>namespace fbz = ::foo::bar::baz;</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US"><span style=""></span>...</span></p>
<p class="MsoNormal" style="" align="left"><span style="font-family: Symbol; color: #006600; font-size: 10pt;" lang="EN-US"><span style="">·<span style='font: 7pt "Times New Roman";'> </span></span></span><span style="" lang="EN-US">}</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; margin-left: 21.3pt; margin-right: 0cm; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">} <span style=""></span>// namespace librarian</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">注意,在头文件中定义的别名,在任何包含这个头文件的文件中都是可见的。所以在公共头文件中(这些头文件可以在工程外被包含),以及间接地被这些公共头文件包含的头文件中,应当避免使用别名。这也是保持</span><span lang="EN-US"><span style="font-family: Times New Roman;">API</span></span><span style="">尽量简洁总目标的一部分。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281539"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.2</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">内嵌类(</span><span lang="EN-US"><span style="font-family: Cambria;">Nested Class</span></span></span></strong></a><strong><span style="font-size: large;"><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">虽然,当内嵌类是接口的一部分时,可以声明为</span><span lang="EN-US"><span style="font-family: Times New Roman;">public</span></span><span style="">,但最好还是使用命名空间将内嵌类声明与全局作用域隔离。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">定义:</span></strong><span style="">在类内部定义的另一个类;这个内部的类也称为成员类(</span><em><span lang="EN-US"><span style="font-family: Times New Roman;">member class</span></span></em><span style="">)。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">class Foo {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""></span>private:</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>// Bar is a member class, nested within Foo.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>class Bar {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>...</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>};</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"></span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">};</span></p>
</div>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">当只有内嵌类的外层类(</span><span lang="EN-US"><span style="font-family: Times New Roman;">enclosing class</span></span><span style="">)使用它时很有用,这时可以将它定义为外层类的成员,从而把它的作用域限定在外层类的内部,避免声明在外部作用域所带来的名称污染(即不会影响到用不到其他的类)。内嵌类可以在外层类中前置声明,然后在</span><span style="" lang="EN-US">.cc</span><span style="">文件中定义。这样一来,就可以避免在外层类的定义中定义整个内嵌类,而且内嵌类一般也只与实现相关。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">内嵌类只能在外层类的定义内前置声明。所以,任何使用</span><span style="" lang="EN-US">Foo::Bar*</span><span style="">指针的头文件都需要包含</span><span style="" lang="EN-US">Foo</span><span style="">类的完整声明。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">除非内嵌类是接口的一部分,否则不要声明为</span><span lang="EN-US"><span style="font-family: Times New Roman;">public</span></span><span style="">的,例如,一个类包含某方法的多个选项。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281540"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.3</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">非成员函数(</span><span lang="EN-US"><span style="font-family: Cambria;">Nonmember</span></span></span></strong></a><strong><span style="font-size: large;"><span style=""><span style="">)、静态成员函数(</span><span lang="EN-US"><span style="font-family: Cambria;"> Static Member</span></span></span><span style=""><span style="">)、全局函数(</span><span lang="EN-US"><span style="font-family: Cambria;">Global Functions</span></span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">优先使用命名空间内的非成员函数或静态成员函数,尽量不要使用全局函数。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">优点:</span></strong><span style="">有时,非成员函数和静态成员函数很有用。将非成员函数放在某命名空间内,可以防止其对全局命名空间的名称污染。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">劣势:</span></strong><span style="">将非成员函数和静态函数作为一个新类的成员函数可能更合理,尤其当这些函数访问大量外部资源或具有大量依赖时。</span></span></p>
<p class="a" style="text-indent: 21.1pt; margin: 6pt 0cm;"><span style="font-size: small;"><strong style=""><span style="">结论:</span></strong><span style="">有时,定义一个类外函数是有用的,甚至是必须的。这样的函数可以是一个静态成员函数或者非成员函数。非成员函数不应依赖外部变量,并且应当总是只存在于一个命名空间内。不要用类把不含共享静态数据的静态成员函数封装起来,把这样的函数放到</span><span lang="EN-US"><a href="#%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"><span style="" lang="EN-US"><span lang="EN-US"><span style="color: #0000ff;">命<span lang="EN-US">名<span lang="EN-US">空间</span></span></span></span></span></a></span><span style="">中</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">和其他类在同一编译单元内定义的函数,如果在别的编译单元中直接调用,可能会引起额外的耦合和连接依赖,静态成员函数尤其明显。这时,应当考虑建立一个新类来封装这些函数,也可以将这些函数封装到独立类库的</span><span lang="EN-US"><a href="#%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%EF%BC%88%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%89"><span style="" lang="EN-US"><span lang="EN-US"><span style="color: #0000ff;">命名<span lang="EN-US">空间</span></span></span></span></a></span><span style="">中。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">如果必须定义一个非成员函数,并且只在当前</span><span style="" lang="EN-US">.cc</span><span style="">文件中使用,使用匿名命名空间或者</span><span style="" lang="EN-US">static</span><span style="">连接关键字(比如</span><span style="" lang="EN-US">static int Foo() {...}</span><span style="">)来限定它的作用域。</span></span></p>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281541"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.4</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">局部变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Local Variable</span></span></span></strong></a><strong><span style="font-size: large;"><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">将函数中的变量作用域限定在尽量小的范围内,并且在定义时就初始化。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">允许在函数内任何地方声明变量。但是,要在尽量小的作用域中声明变量,最好在第一次使用前声明。这样,读代码的人就很容易找到定义,从而知道这个变量是什么类型,初始值是多少。这里要特别强调:定义和初始化应放在同一语句,而不是先定义后再单独进行赋值。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; border-top: #fff0f0 1pt solid; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">int i;</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">i = f();<span style=""> </span>// Bad -- initialization separate from declaration.</span></p>
</div>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">int j = g();<span style=""> </span>// Good -- declaration has initialization.</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">值得注意的是,</span><span lang="EN-US"><span style="font-family: Times New Roman;">gcc</span></span><span style="">中对</span><span style="" lang="EN-US">for (int i = 0; i < 10; ++i)</span><span style="">语句的实现是正确的(变量</span><span style="" lang="EN-US">i</span><span style="">的作用域限定在</span><span style="" lang="EN-US">for</span><span style="">循环内)。因此,在与这个</span><span style="" lang="EN-US">for</span><span style="">循环处于同一作用域中的其他</span><span style="" lang="EN-US">for</span><span style="">循环中还可以使用变量</span><span style="" lang="EN-US">i</span><span style="">。</span><span lang="EN-US"><span style="font-family: Times New Roman;">gcc</span></span><span style="">对</span><span style="" lang="EN-US">if</span><span style="">语句和</span><span style="" lang="EN-US">while</span><span style="">语句中声明的变量的作用域的实现也是正确的。比如:</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">while (const char* p = strchr(str, '/')) str = p + 1;</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">警告:如果变量是一个对象,那么在每次进入作用域时都调用构造函数并创建这个对象,而在出了作用域之后又会调用析构函数来销毁这个对象。</span></span></p>
<div style="border-bottom: #fff0f0 1pt solid; border-left: #fff0f0 4.5pt solid; padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #fff8f8; border-top: #fff0f0 1pt solid; border-right: #fff0f0 1pt solid; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">// Inefficient implementation:</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">for (int i = 0; i < 1000000; ++i) {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>Foo f;<span style=""> </span>// My ctor and dtor get called 1000000 times each.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>f.DoSomething(i);</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #fff8f8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
</div>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">可以将这样的变量声明在循环体外来提高效率。</span></span></p>
<div style="padding-bottom: 3pt; padding-left: 9pt; padding-right: 9pt; background: #f8fff8; padding-top: 3pt;">
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">Foo f;<span style=""> </span>// My ctor and dtor get called once each.</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">for (int i = 0; i < 1000000; ++i) {</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US"><span style=""> </span>f.DoSomething(i);</span></p>
<p class="MsoNormal" style="text-align: left; margin: 0cm 0cm 0pt; background: #f8fff8; padding: 0cm;" align="left"><span style="" lang="EN-US">}</span></p>
</div>
<p class="Heading2ForEnglish" style=""><a name="_Toc288281542"><span style="" lang="EN-US"><span style=""><strong><span style="font-family: Cambria; font-size: large;">1.5</span></strong><span style='font: 7pt "Times New Roman";'> </span></span></span><strong><span style="font-size: large;"><span style="">静态变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Static Variable</span></span></span></strong></a><strong><span style="font-size: large;"><span style=""><span style="">)和全局变量(</span><span lang="EN-US"><span style="font-family: Cambria;">Global Variable</span></span></span><span style="">)</span></span></strong></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">禁止使用静态或全局的类类型变量:它们会引起不易找到的</span><span lang="EN-US"><span style="font-family: Times New Roman;">bug</span></span><span style="">,因为它们的构造和析构的顺序是不固定的。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style=""><span style="font-size: small;">对象如果存储在内存中的静态区(包括全局变量、静态变量、静态类成员变量和函数内部静态变量),必须是简单旧式数据(</span></span><span lang="EN-US"><span style="font-family: Times New Roman; font-size: small;">Plain Old Data</span><a style="" name="_ednref6" href="#_edn6"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vi]</span></span></span></span></span></a></span><span style="font-size: small;"><span style="">),即整型、字符型、单精度型或者简单旧式数据类型的指针、数组、结构体。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">但是,</span><span lang="EN-US"><span style="font-family: Times New Roman;">C++</span></span><span style="">中并未明确规定静态变量的构造函数和析构函数的调用顺序,甚至每次编译生成后的调用顺序可能都是不一样的。这样就可能导致不易发现的</span><span lang="EN-US"><span style="font-family: Times New Roman;">bug</span></span><span style="">。因此,不但禁止将类类型作为全局变量,还禁止使用函数返回值对静态简单旧式数据变量进行初始化,除非这个函数(如</span><span lang="EN-US"><span style="font-family: Times New Roman;">getenv()</span></span><span style="">,或</span><span lang="EN-US"><span style="font-family: Times New Roman;">getpid()</span></span><span style="">)本身并不依赖于其他的全局变量。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">按规定,析构函数的调用顺序与构造函数的调用顺序应当是正好相反的。因为构造函数的调用顺序是不确定的,所以析构函数的调用顺序也是不确定的。例如:在程序运行过程中,一个静态变量已经被销毁了,但是程序依然在运行,也许正好有另外一个线程试图去使用这个变量,这当然会失败。抑或是在调用某“</span><span lang="EN-US"><span style="font-family: Times New Roman;">string</span></span><span style="">”类型静态变量析构函数后,才去调用另一个变量的析构函数,而这个变量内包含有对此</span><span lang="EN-US"><span style="font-family: Times New Roman;">string</span></span><span style="">的引用。</span></span></p>
<p class="a" style="text-indent: 21pt; margin: 6pt 0cm;"><span style="font-size: small;"><span style="">因此,规定静态变量只能是简单旧式数据类型。这条规则明确禁止把</span><span style="" lang="EN-US">vector</span><span lang="EN-US"><span style="font-family: Times New Roman;"> </span></span><span style="">(可以使用</span><span lang="EN-US"><span style="font-family: Times New Roman;">C</span></span><span style="">语言中的数组代替)和</span><span style="" lang="EN-US">string</span><span lang="EN-US"><span style="font-family: Times New Roman;"> </span></span><span style="">(可以使用</span><span style="" lang="EN-US">const char []</span><span style="">)声明为静态。</span></span></p>
<p><span style="">如果需要使用静态的或全局的类类型变量,那么请在</span><span style="" lang="EN-US">main</span><span style="">函数或</span><span style="" lang="EN-US">pthread_once</span><span style="">函数中初始化为一个指针(这个指针将不会被释放)。注意,这个指针必须是裸指针(</span><span style="" lang="EN-US">raw pointer<a style="" name="_ednref7" href="#_edn7"><span class="MsoEndnoteReference"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vii]</span></span></span></span></span></a></span><span style="">),而不能是智能指针(</span><span style="" lang="EN-US">smart pointer</span><span style="">),因为智能指针的析构函数也有上文讨论过的调用顺序问题。</span><span style="font-family: Times New Roman; font-size: small;"> </span></p>
<div style="">
<br><span style="font-family: Times New Roman; font-size: small;">
<hr size="1"></span>
<div id="edn1" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn1" href="#_ednref1"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[i]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">unnamed namespace</span></span><span style="">原意为未命名的命名空间。在</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">中,命名空间分为命名的命名空间和未命名的命名空间。实际上,未命名的命名空间在编译时,编译器也会为它分配一个自动生成的唯一名称,以与其他的命名空间相区分。故这里译为匿名命名空间(不是没有名,而是人看不到它的名字)。与此对应,</span><span lang="EN-US"><span style="font-family: Calibri;">named namespace</span></span><span style="">译为定名命名空间。</span></span></p>
</div>
<div id="edn2" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn2" href="#_ednref2"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[ii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:这里读者需要对</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">的历史有一些了解。</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">是由</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="">语言进化来的。在</span><span lang="EN-US"><span style="font-family: Calibri;">C</span></span><span style="">语言中,所有的方法、函数以及变量等都是全局作用域命名的。但是随着软件工程规模的扩大,人们发现这样很不利于管理(很容易产生同名冲突)。于是有人提出了类的概念(当然,这只是类概念产生的众多原因中的一个)。这样每个类中有自己的方法、函数和变量,与其他类中(以及全局)的相应内容相互区分。故,类与命名空间的共同点就是对方法、函数和变量等名称的隔离(当然,命名空间还可以用来隔离类名)。</span></span></p>
</div>
<div id="edn3" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn3" href="#_ednref3"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">One Definition Rule </span></span><span style="">(缩写:</span><span lang="EN-US"><span style="font-family: Calibri;">ODR</span></span><span style="">)定义为:</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: small;">1.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">任何</span><span style="">编译单元中,模板、类型、函数、对象等最多都只能有一次定义。</span><span style="">当然,它们中有的可以在多处声明。定义就是构造一个实例。</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Calibri; font-size: small;">2.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">在整个程序中,一个对象或内联函数,只能有一处定义。如果使用了某对象或函数,那么这个对象或函数就必须得有唯一的定义。可以声明一个对象或函数,但却不使用它,这时不需要对它进行定义。任何情况下,都不能有多于一次的定义。</span></span></p>
<p class="MsoEndnoteText" style=""><span style="" lang="EN"><span style=""><span style="font-family: Calibri; font-size: small;">3.</span><span style='font: 7pt "Times New Roman";'> </span></span></span><span style="font-size: small;"><span style="">有些内容,如类型、模板、外部内联函数(</span><span lang="EN-US"><span style="font-family: Calibri;">extern</span></span><span style="">关键字修饰的内联函数),可以在多个编译单元中定义。对于一个给定的实体,所有的定义必须一致。不同编译单元中,同名且同类型(同参数)的非外部对象和函数是不同的实体。</span></span></p>
</div>
<div id="edn4" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn4" href="#_ednref4"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[iv]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">gflags</span></span><span style="">是一个库文件包,主要用来处理命令行中的标识。从这点上讲,它可以替代</span><span lang="EN-US"><span style="font-family: Calibri;">getopt()</span></span><span style="">函数。不同的是,它更具灵活性。不仅支持</span><span lang="EN-US"><span style="font-family: Calibri;">C++</span></span><span style="">的类型(如</span><span lang="EN-US"><span style="font-family: Calibri;">string</span></span><span style="">),还可以在使用标识的源代码文件中定义新的标识。</span></span></p>
</div>
<div id="edn5" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn5" href="#_ednref5"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[v]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">undefined behavior</span></span><span style="">是指在</span><span lang="EN-US"><span style="font-family: Calibri;">C/C++</span></span><span style="">中,为了提高实现编译器的灵活性,对某些特定行为,在语言的标准中并没有规定他们的具体表现。所以,不同的编译器中,这些行为的表现可能是不同的。也是下面说不可移植的原因。</span></span></p>
</div>
<div id="edn6" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn6" href="#_ednref6"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vi]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">Plain Old Data</span></span><span style="">,是未经包装,且不含任何面向对象特性的变量类型构成的数据结构。</span></span></p>
</div>
<div id="edn7" style="">
<p class="MsoEndnoteText" style="margin: 0cm 0cm 0pt;"><a style="" name="_edn7" href="#_ednref7"><span class="MsoEndnoteReference"><span lang="EN-US"><span style=""><span class="MsoEndnoteReference"><span style="" lang="EN-US"><span style="color: #0000ff;">[vii]</span></span></span></span></span></span></a><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Calibri;"> </span></span><span style="">译者注:</span><span lang="EN-US"><span style="font-family: Calibri;">raw pointer</span></span><span style="">,即普通指针,与智能指针概念相对应。我们知识,智能指针是经过封装的指针,所以普通指针被译为裸指针。</span></span></p>
</div>
</div>
相关推荐
**Google C++ Style Guide** 是一份由Google官方发布的C++编程规范文档,旨在帮助开发人员编写高质量、可维护性强且易于理解的代码。该文档为C++开发者提供了一套详尽的编码规则与建议,涵盖从基础语法到高级特性...
《Thinking in C++ 2nd Edition》是C++编程领域中的经典著作,由Bruce Eckel撰写,分为两卷,分别为Volume One和Volume Two。这两卷书籍深入浅出地介绍了C++编程语言,不仅适合初学者,也对有经验的程序员提供了深入...
A_Stochastic_Finite-State_Word-Segmentation_Algorithm_for_Chinese.pdf An_efficient_augmented-context-free_parsing_algorithm.pdf An_Efficient_Context_Free_Parsing_Algorithm.pdf Example-based Machine ...
【标题】"Felomeng家庭理财2.01Windows7专版"是一个针对Windows7操作系统设计的财务管理软件。这个版本特别优化了与Windows7的兼容性,确保在该系统上运行顺畅,为用户提供高效的家庭财务规划和管理工具。 【描述】...
运行本软件,须.net framework3.5支持。 2.0x版本直接升级不会造成数据损失。... 本软件自2.0版开始,数据格式与1.xx版本不再兼容,采用了全新的数据管理方式,并且对于字段也略有调整。对此给您造成的不便敬请谅解。
软件的设计理念是将复杂、专业的财务管理知识与技术,转化为普通家庭用户能够轻松掌握和使用的工具,使得每一个家庭成员都能参与到家庭财务的管理中来,从而促进家庭财务状况的透明化和规范化。 软件通过便捷的操作...
Felomeng家庭理财2.23,简单易用的理财软件
1.xx版设计比较失败,2.xx版本采取了完全不同的架构与理念(虽然界面,使用方法上基本保持了一致)。故1.xx代码不再具有保密的必要,拿出来与大家分享。 这是我来北大软院学习前编写的软件,谈不上设计,学习价值...
本工具可以计算: 工资、薪金所得 个体工商户生产、经营所得 企事业单位的承包经营、承 租经营所得 劳务报酬所得 稿酬所得 特许权使用所得 利息、股息、红利所得 财产租赁所得 财产转让所得 ...
VB(Visual Basic)是一种由微软开发的编程环境,主要用于创建Windows桌面应用程序。在这个"VB图片查看程序"中,我们关注的是如何使用VB来实现图片的加载和显示功能。这个程序作为一个学习示例,旨在帮助初学者理解...
1. **C#编程语言**:C#是一种面向对象的编程语言,由微软开发,用于构建Windows平台的应用程序。在本项目中,C#被用来实现文本相似度检测的算法和系统框架,具有高效、易于理解和强大的库支持。 2. **VSM空间向量...
《VC6学习指南配套代码》是针对Microsoft Visual C++ 6.0(简称VC6)这一经典编程环境的学习资源,通常与《learn microsoft visual c++6.0 now》这本书的实践部分相配合。这本书旨在帮助读者快速掌握C++编程语言以及...
在`Felomeng.MoreEffectiveVSMSimilarity.sln`和`Felomeng.VSMSimilarity`这两个文件中,很可能包含了项目解决方案和主要的相似度计算类。通过打开并分析这些文件,我们可以看到具体的实现代码,包括如何构建词汇表...
【VB计算器】是一种基于Visual Basic(VB)编程语言开发的简单计算器应用,它通常用于教学目的,帮助初学者理解可视化编程的基本概念。VB是一种面向对象的编程语言,由微软公司开发,广泛应用于Windows应用程序的...
个人所得税计算器的作用在于自动化这些计算过程,输入相关收入和扣除信息,即可快速得到准确的税额。例如,Felomeng.PersonalTaxCalculatorSetup可能就是一款个人所得税计算器的安装程序,用户下载安装后,可以输入...
1. **安装JDK**: - **目的**:bddbot作为一款基于Java的应用程序,需要Java环境来运行。 - **操作**:安装Java开发工具包(JDK),并进行必要的环境变量设置。 - **环境变量设置**: - **JAVA_HOME**:指向JDK...
在C#编程环境中,我们可以构建HMM来实现中文分词,这是一种将文本字符串分割成有意义的词语的过程。 **HMM基本概念** 1. **状态(State)**: 在HMM中,状态是不可见的,代表了模型内部的一种动态过程。 2. **观测...
1. **IKVM.Runtime.dll**:这是IKVM的核心组件,它实现了Java虚拟机(JVM)的大部分功能,包括字节码解释器、垃圾收集器和类加载器等。它使得.NET平台能够理解和执行Java字节码。 2. **IKVM.OpenJDK.ClassLibrary....
7. **API接口**:提供C、C++、Java、Python等编程语言的接口使用示例,帮助开发者将LibSVM集成到自己的项目中。 8. **性能优化**:可能包括关于并行计算、内存管理等方面的建议,以提高模型训练和预测的效率。 9. ...