📄 effective c++ 2e item28.htm
字号:
// 都没有引入到本空间<BR>
...
</P>
<P>}</P>
<P>void f3()<BR>{<BR> cout <<
sdm::BOOK_VERSION; //
使得BOOK_VERSION<BR>
// 在本语句有效<BR>
...
</P>
<P> double d = BOOK_VERSION; //
错误!
BOOK_VERSION<BR>
// 不在本空间</P>
<P> Handle h =
getHandle(); // 错误!
Handle和getHandle<BR>
// 都没有引入到本空间<BR>
...
</P>
<P>}</P>
<P>(有些名字空间没有名字。这种没命名的名字空间一般用于限制名字空间内部元素的可见性。详见条款M31。)</P>
<P>名字空间带来的最大的好处之一在于:潜在的二义不会造成错误(参见条款26)。所以,从多个不同的名字空间引入同一个符号名不会造成冲突(假如确实真的从不使用这个符号的话)。例如,除了名字空间sdm外,假如还要用到下面这个名字空间:</P>
<P>namespace AcmeWindowSystem {</P>
<P> ...</P>
<P> typedef int Handle;</P>
<P> ...</P>
<P>}</P>
<P>只要不引用符号Handle,使用sdm和AcmeWindowSystem时就不会有冲突。假如真的要引用,可以明确地指明是哪个名字空间的Handle:</P>
<P>void f()<BR>{<BR> using namespace
sdm;
// 引入sdm里的所有符号<BR> using namespace AcmeWindowSystem; //
引入Acme里的所有符号</P>
<P>
...
//
自由地引用sdm<BR>
//
和Acme里除Handle之外<BR>
// 的其它符号</P>
<P> Handle
h;
// 错误! 哪个Handle?</P>
<P> sdm::Handle
h1;
// 正确, 没有二义</P>
<P> AcmeWindowSystem::Handle
h2; // 也没有二义</P>
<P> ...</P>
<P>}</P>
<P>假如用常规的基于头文件的方法来做,只是简单地包含sdm.h和acme.h,这样的话,由于Handle有多个定义,编译将不能通过。</P>
<P>名字空间的概念加入到C++标准的时间相对较晚,所以有些人会认为它不太重要,可有可无。但这种想法是错误的,因为C++标准库(参见条款49)里几乎所有的东西都存在于名字空间std之中。这可能令你不以为然,但它却以一种直接的方式影响到你:这就是为什么C++提供了那些看起来很有趣的、没有扩展名的头文件,如<iostream>,
<string>等。详细介绍参见条款49。</P>
<P>由于名字空间的概念引入的时间相对较晚,有些编译器可能不支持。就算是这样,那也没理由污染全局名字空间,因为可以用struct来近似实现namespace。可以这样做:先创建一个结构用以保存全局符号名,然后将这些全局符号名作为静态成员放入结构中:</P>
<P>// 用于模拟名字空间的一个结构的定义<BR>struct sdm {<BR> static const double
BOOK_VERSION;<BR> class Handle { ... };<BR> static Handle&
getHandle();<BR>};</P>
<P>const double sdm::BOOK_VERSION = 2.0; //
静态成员的定义</P>
<P>现在,如果有人想访问这些全局符号名,只用简单地在它们前面加上结构名作为前缀:</P>
<P>void f()<BR>{<BR> cout << sdm::BOOK_VERSION;</P>
<P> ...</P>
<P> sdm::Handle h = sdm::getHandle();</P>
<P> ...<BR>}</P>
<P>但是,如果全局范围内实际上没有名字冲突,用户就会觉得加修饰符麻烦而多余。幸运的是,还是有办法来让用户选择使用它们或忽略它们。</P>
<P>对于类型名,可以用类型定义(typedef)来显式地去掉空间引用。例如,假设结构s(模拟的名字空间)内有个类型名T,可以这样用typedef来使得T成为S::T的同义词:</P>
<P>typedef sdm::Handle Handle;</P>
<P>对于结构中的每个(静态)对象X,可以提供一个(全局)引用X,并初始化为S::X:</P>
<P>const double& BOOK_VERSION = sdm::BOOK_VERSION;</P>
<P>老实说,如果读了条款47,你就会不喜欢定义一个象BOOK_VERSION这样的非局部静态对象。(你就会用条款47中所介绍的函数来取代这样的对象)</P>
<P>处理函数的方法和处理对象一样,但要注意,即使定义函数的引用是合法的,但代码的维护者会更喜欢你使用函数指针:</P>
<P>sdm::Handle& (* const getHandle)() = //
getHandle是指向sdm::getHandle<BR>
sdm::getHandle;
// 的const 指针 (见条款21)</P>
<P>注意getHandle是一个常指针。因为你当然不想让你的用户将它指向别的什么东西,而不是sdm::getHandle,对不对?</P>
<P>(如果真想知道怎么定义一个函数的引用,看看下面:</P>
<P>sdm::Handle& (&getHandle)() = //
getHandle是指向<BR>
sdm::getHandle;
// sdm::getHandle的引用</P>
<P>我个人认为这样的做法也很好,但你可能以前从没见到过。除了初始化的方式外,函数的引用和函数的常指针在行为上完全相同,只是函数指针更易于理解。)</P>
<P>有了上面的类型定义和引用,那些不会遭遇全局名字冲突的用户就会使用没有修饰符的类型和对象名;相反,那些有全局名字冲突的用户就会忽略类型和引用的定义,代之以带修饰符的符号名。还要注意的是,不是所有用户都想使用这种简写名,所以要把类型定义和引用放在一个单独的头文件中,不要把它和(模拟namespace的)结构的定义混在一起。</P>
<P>struct是namespace的很好的近似,但实际上还是相差很远。它在很多方面很欠缺,其中很明显的一点是对运算符的处理。如果运算符被定义为结构的静态成员,它就只能通过函数调用来使用,而不能象常规的运算符所设计的那样,可以通过自然的中缀语法来使用:</P>
<P>// 定义一个模拟名字空间的结构,结构内部包含Widgets的类型<BR>//
和函数。Widgets对象支持operator+进行加法运算<BR>struct widgets {<BR> class Widget { ...
};</P>
<P><BR> // 参见条款21:为什么返回const<BR> static const Widget operator+(const
Widget&
lhs,<BR>
const Widget& rhs);</P>
<P> ...</P>
<P>};</P>
<P>// 为上面所述的Widge和operator+ <BR>// 建立全局(无修饰符的)名称</P>
<P>typedef widgets::Widget Widget;</P>
<P><BR>const Widget (* const operator+)(const
Widget&, //
错误!<BR>
const Widget&); //
operator+不能是指针名<BR> </P>
<P>Widget w1, w2, sum;</P>
<P>sum = w1 +
w2;
// 错误!
本空间没有声明<BR>
// 参数为Widgets 的operator+</P>
<P>sum = widgets::operator+(w1, w2);
// 合法,
但不是<BR>
// "自然"的语法</P>
<P>正因为这些限制,所以一旦编译器支持,就要尽早使用真正的名字空间。</P><BR><BR></DIV></DIV></DIV><BR><BR>
<SCRIPT src="Effective C++ 2e Item28.files/get_readnum.htm"></SCRIPT>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#990000 id=white><FONT
color=#ffffff>对该文的评论</FONT></TH></TR></TBODY></TABLE><BR>
<SCRIPT language=javascript>
<!--
function isEmpty(s)
{
return ((s == null) || (s.length == 0))
}
function submit1()
{
if (isEmpty(document.add_critique.csdnname.value) || isEmpty(document.add_critique.csdnpassword.value) || isEmpty(document.add_critique.critique_content.value))
{
alert('登陆名,密码,评论不能为空!!!!') ;
return false;
}
document.add_critique.submit();
}
//-->
</SCRIPT>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#990000 id=white><FONT
color=#ffffff>发表评论</FONT></TH></TR></TBODY></TABLE>
<TABLE align=center bgColor=#ffffff border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TD>
<FORM action=/develop/add_critique.asp method=post
name=add_critique><INPUT name=critique_add type=hidden value=add> <INPUT
name=from type=hidden value=8989> 评论人: <INPUT name=csdnname>
密码: <INPUT name=csdnpassword type=password>
评论:<BR> <TEXTAREA cols=100 name=critique_content rows=8></TEXTAREA><BR>
<INPUT name=ubmit onclick=javascript:submit1(); type=button value=发表评论>
<INPUT name=id type=hidden value=8989> </FORM></TD></TR></TBODY></TABLE>
<TABLE border=0 width=770>
<TBODY>
<TR>
<TD>
<TABLE border=0 cellPadding=2 width=770>
<TBODY>
<TR>
<TD height=10></TD></TR>
<TR>
<TD align=left width=130><A
href="http://www.csdn.net/news/looknews.asp?id=2313"
target=_blank><IMG border=0
src="http://www.csdn.net/job/images/csdn_job.gif"></A> </TD>
<TD align=middle width=510>
<OBJECT classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000
codeBase=http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0
height=60 id=Movie1 width=468><PARAM NAME="movie" VALUE="http://www.csdn.net/images/ad/csdn_media.swf"><PARAM NAME="quality" VALUE="high">
<EMBED src="http://www.csdn.net/images/ad/csdn_media.swf"
quality=high WIDTH=468 HEIGHT=60
TYPE="application/x-shockwave-flash"
PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
</EMBED> </OBJECT></TD>
<TD align=middle width=130><A
href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG
border=0 src="http://www.csdn.net/images/biaoshi.gif"></A>
</TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD>
<TABLE align=default bgColor=#1f60a0 border=0 cellPadding=0 cellSpacing=0
height=20 width=770>
<TBODY>
<TR align=middle class=font13px vAlign=center>
<TD class=font13px height=2 vAlign=center width=90></TD>
<TD rowSpan=2 width=2><IMG height=13
src="http://www.csdn.net/images/ad4.gif" width=2></TD>
<TD class=font13px height=2 width=90></TD>
<TD rowSpan=2 width=3><FONT color=#ffffff><IMG height=13
src="http://www.csdn.net/images/ad4.gif" width=2></FONT></TD>
<TD class=font13px height=2 width=90></TD>
<TD rowSpan=2 width=2><IMG height=13
src="http://www.csdn.net/images/ad4.gif" width=2></TD>
<TD class=font13px height=2 width=90></TD>
<TD rowSpan=2 width=3><FONT color=#ffffff><IMG height=13
src="http://www.csdn.net/images/ad4.gif" width=2></FONT></TD>
<TD height=2 width=350><FONT color=#ffffff></FONT></TD>
<TD rowSpan=2 width=10><FONT color=#ffffff><IMG height=11
src="http://www.csdn.net/images/ad3.gif" width=6></FONT></TD>
<TD class=font13px height=2 width=60></TD></TR>
<TR align=middle class=font14px vAlign=center>
<TD class=font13px vAlign=center width=90><A
href="http://www.csdn.net/intro/intro.shtm"><FONT
color=#ffffff>美达美简介</FONT></A></TD>
<TD class=font13px width=90><A
href="http://www.csdn.net/intro/ad.shtm"><FONT
color=#ffffff>广告服务</FONT></A></TD>
<TD class=font13px width=90><A
href="http://www.csdn.net/English/"><FONT
color=#ffffff>英语步步高</FONT></A></TD>
<TD class=font13px width=90><A href="http://www.csdn.net/dev/"><FONT
color=#ffffff>程序员大本营</FONT></A></TD>
<TD align=right width=350><SPAN class=font13px><A
href="mailto:webmaster@csdn.net"><FONT
color=#ffffff>百联美达美科技有限公司</FONT></A></SPAN><FONT color=#ffffff><SPAN
class=font13px> </SPAN></FONT></TD>
<TD class=font13px width=60><FONT color=#ffffff>版权所有</FONT>
<SCRIPT>document.write("<img src=http://202.106.156.10/stat.asp?user=designol&refer="+escape(document.referrer)+"&cur="+escape(document.URL)+" width=0 height=0 border=0>");</SCRIPT>
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -