c++中的命名空间是什么.docx

上传人:b****2 文档编号:1163772 上传时间:2023-04-30 格式:DOCX 页数:16 大小:20.54KB
下载 相关 举报
c++中的命名空间是什么.docx_第1页
第1页 / 共16页
c++中的命名空间是什么.docx_第2页
第2页 / 共16页
c++中的命名空间是什么.docx_第3页
第3页 / 共16页
c++中的命名空间是什么.docx_第4页
第4页 / 共16页
c++中的命名空间是什么.docx_第5页
第5页 / 共16页
c++中的命名空间是什么.docx_第6页
第6页 / 共16页
c++中的命名空间是什么.docx_第7页
第7页 / 共16页
c++中的命名空间是什么.docx_第8页
第8页 / 共16页
c++中的命名空间是什么.docx_第9页
第9页 / 共16页
c++中的命名空间是什么.docx_第10页
第10页 / 共16页
c++中的命名空间是什么.docx_第11页
第11页 / 共16页
c++中的命名空间是什么.docx_第12页
第12页 / 共16页
c++中的命名空间是什么.docx_第13页
第13页 / 共16页
c++中的命名空间是什么.docx_第14页
第14页 / 共16页
c++中的命名空间是什么.docx_第15页
第15页 / 共16页
c++中的命名空间是什么.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

c++中的命名空间是什么.docx

《c++中的命名空间是什么.docx》由会员分享,可在线阅读,更多相关《c++中的命名空间是什么.docx(16页珍藏版)》请在冰点文库上搜索。

c++中的命名空间是什么.docx

c++中的命名空间是什么

C++中的命名空间是什么?

问:

命名空间是什么?

 

像usingnamespaceSystem;

usingnamespacestd;这些是什么意思?

 

答:

1、命名空间是为了防止名字(符号)冲突而把一系列的类型、变量、函数放在一起的一种方式,命名控件要和变量作用域放在一起来理解,在作用域范围内使用命名空间就可以访问该命名空间内定义的符号。

命名空间用如下的方式定义:

namespaceSystem

{

//符号定义,类型、变量、函数等。

};

和类、结构类似,但不能实例化,只可以引用。

2、名字空间,说白了,就是一个区域,为了防止命名冲突,可以保证,在某个名字空间里的命名对象不会产生冲突。

STd就是这样的,你可以定义自己的名字空间:

namespacemyspace

{

classA

{

}

classB

{

}

……

struct

{

}

……

}

外人使用时相当与这么用myspace:

:

A

不会冲突了吧,前面有个限定(用哪个空间下的……,myspace:

:

可以避免导致全局命名冲突问题。

举一个实例,请注意以下两个头文件:

//one.h

charfunc(char);

classString{...};

//somelib.h

classString{...};

如果按照上述方式定义,那么这两个头文件不可能包含在同一个程序中,因为String类会发生冲突。

所谓命名空间,是一种将程序库名称封装起来的方法,它就像在各个程序库中立起一道道围墙。

比如:

//one.h

namespaceone

{

charfunc(char);

classString{...};

}

//somelib.h

namespaceSomeLib

{

classString{...};

}

现在就算在同一个程序中使用String类也不会发生冲突了,因为他们分别变成了:

one:

:

String()以及Somelib:

:

String()

这样,就可以通过声明命名空间来区分不同的类或函数等了。

比如C++标准库定义了命名空间:

std,其中包含容器vector,示例如下:

#include"stdafx.h"

#include

#include

#include

usingnamespacestd;

intmain(intargc,char*argv[])

{

 constintarraysize=7;

 intia[arraysize]={0,1,2,3,4,5};

 file:

//定义容器vector

vectorivect(ia,ia+arraysize);

 vector:

:

iteratorit1=find(ivect.begin(),ivect.end(),4);

 if(it1==ivect.end())

cout<<"4notfound"<

 else

cout<<"4found"<<*it1<

 return0;

}

输出结果为:

4found4.

3、(本部分参考网页:

在C++中,名称(name)可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。

为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入了关键字namespace(命名空间/名字空间/名称空间/名域),可以更好地控制标识符的作用域。

MFC中并没有使用命名空间,但是在.NET框架、MC++和C++/CLI中,都大量使用了命名空间。

1)作用域与命名空间

--[if!

supportLists]-->l

--[endif]-->相关概念

与命名空间相关的概念有:

--[if!

supportLists]-->n

--[endif]-->声明域(declarationregion)——声明标识符的区域。

如在函数外面声明的全局变量,它的声明域为声明所在的文件。

在函数内声明的局部变量,它的声明域为声明所在的代码块(例如整个函数体或整个复合语句)。

--[if!

supportLists]-->n

--[endif]-->潜在作用域(potentialscope)——从声明点开始,到声明域的末尾的区域。

因为C++采用的是先声明后使用的原则,所以在声明点之前的声明域中,标识符是不能用的。

即,标识符的潜在作用域,一般会小于其声明域。

--[if!

supportLists]-->n

--[endif]-->作用域(scope)——标识符对程序可见的范围。

标识符在其潜在作用域内,并非在任何地方都是可见的。

例如,局部变量可以屏蔽全局变量、嵌套层次中的内层变量可以屏蔽外层变量,从而被屏蔽的全局或外层变量在其倍屏蔽的区域内是不可见的。

所以,一个标识符的作用域可能小于其潜在作用域。

--[if!

supportLists]-->l

--[endif]-->命名空间

命名空间(namespace)是一种描述逻辑分组的机制,可以将按某些标准在逻辑上属于同一个集团的声明放在同一个命名空间中。

原来C++标识符的作用域分成三级:

代码块({……},如复合语句和函数体)、类和全局。

现在,在其中的类和全局之间,标准C++又添加了命名空间这一个作用域级别。

命名空间可以是全局的,也可以位于另一个命名空间之中,但是不能位于类和代码块中。

所以,在命名空间中声明的名称(标识符),默认具有外部链接特性(除非它引用了常量)。

在所有命名空间之外,还存在一个全局命名空间,它对应于文件级的声明域。

因此,在命名空间机制中,原来的全局变量,现在被认为位于全局命名空间中。

标准C++库(不包括标准C库)中所包含的所有内容(包括常量、变量、结构、类和函数等)都被定义在命名空间std(standard标准)中了。

2)定义命名空间

有两种形式的命名空间——有名的和无名的。

命名空间的定义格式为:

(取自C++标准文档)

named-namespace-definition:

namespaceidentifier{namespace-body}

unnamed-namespace-definition:

namespace{namespace-body}

namespace-body:

declaration-seqopt

即:

(自己翻译并改写的)

有名的命名空间:

namespace命名空间名

{

//声明序列可选

}

无名的命名空间:

namespace

{

//声明序列可选

 }

命名空间的成员,是在命名空间定义中的花括号内声明了的名称。

可以在命名空间的定义内,定义命名空间的成员(内部定义)。

也可以只在命名空间的定义内声明成员,而在命名空间的定义之外,定义命名空间的成员(外部定义)。

命名空间成员的外部定义的格式为:

命名空间名:

:

成员名……

例如:

//out.h

namespaceOuter

{

//命名空间Outer的定义

inti;//命名空间Outer的成员i的内部定义

namespaceInner

{

//子命名空间Inner的内部定义

voidf(){i++;}//命名空间Inner的成员f()的内部定义,其中的i为Outer:

:

i

inti;

voidg(){i++;}//命名空间Inner的成员g()的内部定义,其中的i为Inner:

:

i

voidh();//命名空间Inner的成员h()的声明

}

voidf();//命名空间Outer的成员f()的声明

//namespaceInner2;//错误,不能声明子命名空间

}

voidOuter:

:

f(){i--;}//命名空间Outer的成员f()的外部定义

voidOuter:

:

Inner:

:

h(){i--;}//命名空间Inner的成员h()的外部定义

//namespaceOuter:

:

Inner2{/*……*/}//错误,不能在外部定义子命名空间

注意:

(1)、不能在命名空间的定义中声明(另一个嵌套的)子命名空间,只能在命名空间的定义中定义子命名空间。

(2)、也不能直接使用“命名空间名:

:

成员名……”定义方式,为命名空间添加新成员,而必须先在命名空间的定义中添加新成员的声明。

(3)、另外,命名空间是开放的,即可以随时把新的成员名称加入到已有的命名空间之中去。

方法是,多次声明和定义同一命名空间,每次添加自己的新成员和名称。

例如:

namespaceA

{

inti;

voidf();

}//现在A有成员i和f()

namespaceA

{

intj;

voidg();

}//现在A有成员i、f()、j和g()

还可以用多种方法,来组合现有的命名空间,让它们为我所用。

例如:

namespaceMy_lib

{

usingnamespaceHis_string;

usingnamespaceHer_vector;

usingYour_list:

:

List;

voidmy_f(String&,List&);

}

……

usingnamespaceMy_lib;

……

Vectorvs[5];

Listli[10];

my_f(vs[2],li[5]);

3)使用命名空间

--[if!

supportLists]-->l

--[endif]-->作用域解析运算符(:

:

对命名空间中成员的引用,需要使用命名空间的作用域解析运算符:

:

例如:

//out1.cpp

#include"out.h"

#include

intmain()

{

Outer:

:

i=0;

Outer:

:

f();//Outer:

:

i=-1;

Outer:

:

Inner:

:

f();//Outer:

:

i=0;

Outer:

:

Inner:

:

i=0;

Outer:

:

Inner:

:

g();//Inner:

:

i=1;

Outer:

:

Inner:

:

h();//Inner:

:

i=0;

std:

:

cout<<"Hello,World!

"<

:

endl;

std:

:

cout<<"Outer:

:

i="<

:

i<<",Inner:

:

i="<

:

Inner:

:

i<

:

endl;

}

--[if!

supportLists]-->l

--[endif]-->using指令(usingnamespace)

为了省去每次调用Inner成员和标准库的函数和对象时,都要添加Outer:

:

Inner:

:

和sta:

:

的麻烦,可以使用标准C++的using编译指令来简化对命名空间中的名称的使用。

格式为:

usingnamespace命名空间名[:

:

命名空间名……];

在这条语句之后,就可以直接使用该命名空间中的标识符,而不必写前面的命名空间定位部分。

因为using指令,使所指定的整个命名空间中的所有成员都直接可用。

例如:

//out2.cpp

#include"out.h"

#include

//usingnamespaceOuter;//编译错误,因为变量i和函数f()有名称冲突

usingnamespaceOuter:

:

Inner;

usingnamespacestd;

intmain()

{

Outer:

:

i=0;

Outer:

:

f();//Outer:

:

i=-1;

f();//Inner:

:

f(),Outer:

:

i=0;

i=0;//Inner:

:

i

g();//Inner:

:

g(),Inner:

:

i=1;

h();//Inner:

:

h(),Inner:

:

i=0;

cout<<"Hello,World!

"<

cout<<"Outer:

:

i="<

:

i<<",Inner:

:

i="<

}

又例如:

(.NET框架)

usingnamespaceSystem:

:

Drawing:

:

Imaging;

usingnamespaceSystem:

:

Window:

:

Forms:

:

Design:

:

Behavior;

--[if!

supportLists]-->l

--[endif]-->using声明(using)

除了可以使用using编译指令(组合关键字usingnamespace)外,还可以使用using声明来简化对命名空间中的名称的使用。

格式为:

using命名空间名:

:

[命名空间名:

:

……]成员名;

注意:

关键字using后面并没有跟关键字namespace,而且最后必须为命名空间的成员名(而在using编译指令的最后,必须为命名空间名)。

与using指令不同的是,using声明只是把命名空间的特定成员的名称,添加该声明所在的区域中,使得该成员可以不需要采用,(多级)命名空间的作用域解析运算符来定位,而直接被使用。

但是该命名空间的其他成员,仍然需要作用域解析运算符来定位。

例如:

//out3.cpp

#include"out.h"

#include

usingnamespaceOuter;//注意,此处无:

:

Inner

usingnamespacestd;

//usingInner:

:

f;//编译错误,因为函数f()有名称冲突

usingInner:

:

g;//此处省去Outer:

:

,是因为Outer已经被前面的using指令作用过了

usingInner:

:

h;

intmain()

{

i=0;//Outer:

:

i

f();//Outer:

:

f(),Outer:

:

i=-1;

Inner:

:

f();//Outer:

:

i=0;

Inner:

:

i=0;

g();//Inner:

:

g(),Inner:

:

i=1;

h();//Inner:

:

h(),Inner:

:

i=0;

cout<<"Hello,World!

"<

cout<<"Outer:

:

i="<

:

i="<

:

i<

}

--[if!

supportLists]-->l

--[endif]-->using指令与using声明的比较

可见,using编译指令和using声明,都可以简化对命名空间中名称的访问。

using指令使用后,可以一劳永逸,对整个命名空间的所有成员都有效,非常方便。

而using声明,则必须对命名空间的不同成员名称,一个一个地去声明,非常麻烦。

但是,一般来说,使用using声明会更安全。

因为,using声明只导入指定的名称,如果该名称与局部名称发生冲突,编译器会报错。

而using指令导入整个命名空间中的所有成员的名称,包括那些可能根本用不到的名称,如果其中有名称与局部名称发生冲突,则编译器并不会发出任何警告信息,而只是用局部名去自动覆盖命名空间中的同名成员。

特别是命名空间的开放性,使得一个命名空间的成员,可能分散在多个地方,程序员难以准确知道,别人到底为该命名空间添加了哪些名称。

虽然使用命名空间的方法,有多种可供选择。

但是不能贪图方便,一味使用using指令,这样就完全背离了设计命名空间的初衷,也失去了命名空间应该具有的防止名称冲突的功能。

一般情况下,对偶尔使用的命名空间成员,应该使用命名空间的作用域解析运算符来直接给名称定位。

而对一个大命名空间中的经常要使用的少数几个成员,提倡使用using声明,而不应该使用using编译指令。

只有需要反复使用同一个命名空间的许多数成员时,使用using编译指令,才被认为是可取的。

例如,如果一个程序(如上面的outi.cpp)只使用一两次cout,而且也不使用std命名空间中的其他成员,则可以使用命名空间的作用域解析运算符来直接定位。

如:

#include

……

std:

:

cout<<"Hello,World!

"<

:

endl;

std:

:

cout<<"Outer:

:

i="<

:

i<<",Inner:

:

i="<

:

Inner:

:

i<

:

endl;

又例如,如果一个程序要反复使用std命名空间中的cin、cout和cerr(如上面的outi.cpp),而不怎么使用其他std命名空间中的其他成员,则应该使用using声明而不是using指令。

如:

#include

……

usingstd:

:

cout;

cout<<"Hello,World!

"<

cout<<"Outer:

:

i="<

:

i<<",Inner:

:

i="<

:

Inner:

:

i<

4)命名空间的名称

--[if!

supportLists]-->l

--[endif]-->命名空间别名

标准C++引入命名空间,主要是为了避免成员的名称冲突。

若果用户都给自己的命名空间取简短的名称,那么这些(往往同是全局级的)命名空间本身,也可能发生名称冲突。

如果为了避免冲突,而为命名空间取很长的名称,则使用起来就会不方便。

这是一个典型的两难问题。

标准C++为此提供了一种解决方案——命名空间别名,格式为:

namespace别名=命名空间名;

例如:

(AT&T美国电话电报公司)

namespaceAmerican_Telephone_and_Telegraph

{

//命名空间名太长

classString

{

 String(constchar*);

 //……

 }

}

American_Telephone_and_Telegraph:

:

Strings1//使用不方便

=newAmerican_Telephone_and_Telegraph:

:

String("Grieg");

namespaceATT=American_Telephone_and_Telegraph;//定义别名

ATT:

:

Strings2=newATT:

:

String("Bush");//使用方便

ATT:

:

Strings3=newATT:

:

String("Nielsen");

--[if!

supportLists]-->l

--[endif]-->无名命名空间

引用命名空间

标准C++引入命名空间,除了可以避免成员的名称发生冲突之外,还可以使代码保持局部性,从而保护代码不被他人非法使用。

如果你的目的主要是后者,而且又为替命名空间取一个好听、有意义、且与别人的命名空间不重名的名称而烦恼的话,标准C++还允许你定义一个无名命名空间。

你可以在当前编译单元中(无名命名空间之外),直接使用无名命名空间中的成员名称,但是在当前编译单元之外,它又是不可见的。

无名命名空间的定义格式为:

namespace

{

//声明序列可选

}

实际上,上面的定义等价于:

(标准C++中有一个隐含的使用指令)

namespace$$$

{

//声明序列可选

}

usingnamespace$$$;

例如:

namespace

{

 inti;

 voidf(){/*……*/}

}

intmain()

{

 i=0;//可直接使用无名命名空间中的成员i

 f();//可直接使用无名命名空间中的成员f()

}

4、类名也是一种命名空间,嵌套类也相当于嵌套命名空间,例如:

intA:

:

B:

:

func()

{

return1;

}

上面这个函数定义中的A和B既可以是命名空间,也能是类名,它能是多种声明方式:

声明一:

namespaceA

{

namespaceB

{

intfunc();

};

};

声明二:

namespaceA

{

classB

{

intfunc();

};

};

声明三:

classA

{

classB

{

intfunc();

};

};

但两者其实还有很大的区别:

(1)、命名空间里面可以嵌套命名空间或者类,但类里面不能嵌套定义命名空间,只能嵌套定义类。

(2)、类名是一种命名空间,但更多的作用是限定作用域;命名空间并不限定作用域,它只是一种符号名称的扩展。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2