namespace 是C++中的一个新的特性,它的出现只要是为了避免出现名字污染。
JAVA语言中的packing包和C++的namespace功能差不多
*************************************************************************
1.引入namespace的理由
这是一个非常非常重要的特性,它使得C++可以更加方便地整合第三方的库,进行大规模的开发。
很多C++的标准对象都封装在一些名字空间中,
你要引用的话可以 namespacename::object来引用,也可以先申明引用 namespace,
语句是 using namespace namespacename,以后就可以直接用你的object了。
以下是引用内容:"C++里引入namespace的目的就是为了避免污染全局名字空间,简单地说,就是为了避免和减少命名冲突。
一旦一个程序写大了,就很难避免重名,特别是多人合作的情况下。
过去C中的解决方法只有靠人为的注意,并且加长名字,以避免重名。
这样做会使得一些名字看上去没有意义或者难以理解,
而程序员在写程序的时候,也受这个问题的限制,不能自由地命名自己使用的变量或者函数。
而有了namespace就不存在这些问题了,这就是C++引入namespace这个概念所带来的便利。"
这么看来,C++采用名字空间的办法,
解决了“相同的函数名,或变量名,或者两个不同的库里面有相同的函数名,这样的话,就会引起混乱,
不是连接不上,就是造成程序死掉”的这个问题,通过不同的名字空间,我们可以起相同的函数名和变量名,这样不会引起冲突。
***********************************************************************************************
2.namespace知识
名字空间允许像类,对象和函数一样的一组实体归属于一个名称。
把一个全局的范围化分成许多子的范围,每一个小的范围都有它自己的名字。
名字空间的格式是:
namespace identifier{
entities
}
包含在名字空间下的任何类,对象和函数中设立的实体必须是有效的标签符,例如:
namespace myNamespace{
int a, b;
}
种情况,在被调用的名字空间myNamespace内部变量a和变量b被定义成了一个普通的变量,
为了从myNamespace外部访问这些变量,我们必须使用作用域操作符::,
例如,从myNamespace外部访问前面定义的变量,我们要这样写:
general::a
general::b
名字空间的功能一个全局的对象或者函数像另外一个对象一样使用了同一个标识符时特别有用,会引起重定义的错误,例如:
//namespace
#include <iostream>
using namespace std;
namespace first{
int var = 5;
}
namespace second{
double var = 3.1416;
}
int main() {
cout << first::var << endl;
cout << second::var <<endl;
return 0;
}
程序运行如下:
5
3.1416
我们使用了两个相同名字的全局变量:var。
一个是被定义在first名字空间里的,另一个是被定义在second名字空间内的。
因为有了名字空间所以没有发生重定义的错误。
using
使用using 这个关键字是为了将一个来到名字空间内的名字介绍到当前声明的区域,例如:
//namespace
#include <iostream>
using namespace std;
namespace first{
int x = 5;
int y = 10;
}
namespace second{
double x = 3.1416;
double y = 2.7183;
}
int main() {
using first::x;
using second::y;
cout << x << endl;
cout << y <<endl;
cout <<first::y <<endl;
cout <<second::x <<endl;
return 0;
}
程序运行如下:
5
2.7183
10
3.1416
如何注意这段代码,x(没有任何名字空间标识符)是引用first::x,
而y引用second::y,正是由于我们在前面指定了using这个声明,所以们仍然要使用标识符全名来访问first::y 和 second::x。
关键字using也能直接指向一个实体名字空间。
//namespace
#include <iostream>
using namespace std;
namespace first{
int x = 5;
int y = 10;
}
namespace second{
double x = 3.1416;
double y = 2.7183;
}
int main() {
using namespace first;
cout << x << endl;
cout << y <<endl;
cout <<second::x <<endl;
cout <<second::y <<endl;
return 0;
}
程序运行如下:
5
10
3.1416
2.7183
这个情况,我们定义过using namespace frist,所有直接使用x和y没有使用名字空间标识符而是引用了定义的名字空间frist。
using和using namespace 仅仅是在同一个块里有效,它们规定在整个代码内,是否是在全局范围里直接使用,
例如,如果我们打算首先使用一个名字空间的对象,再使用别外一个名字空间的对象,我们应该这样做:
//namespace
#include <iostream>
using namespace std;
namespace first{
int x = 5;
}
namespace second{
double x = 3.1416;
}
int main() {
using namespace first;{
cout << x << endl;
}
{
using namespace second;
cout << x <<endl;
}
return 0;
}
程序运行如下:
5
3.1416
名字空间别名(Namespace alias)
我们能改变一个已经存在的名字空间的命名,相应的格式如下:
namespace new_name = current_name;
名字空间std (namespace std)
C++标准类库中的所有实体都定义在名字空间std中,
这就是为什么我们通常需要包含一个using namespace std,
描述在所有的程序中使用的实体都定义在iostream中。
******************************************************************
名字空间的补充
C++为类名的冲突提供一个解决方案,即名字空间(namespace)
下面的程序定义了两个名字空间,一个是anamespace,另一个是anothernamespace,
这两个名字空间都包含了一个叫point的类.
#include<cstdlib>
#include<iostream>
using namespace std;
namespace anamespace//名字空间anamespace
{
class point
{
public:
point()
{
x=y=0;
}
void SetX(int xvalue)
{
x=xvalue;
}
int GetX(void)
{
return (x);
}
void SetY(int yvalue)
{
y=yvalue;
}
int GetY(void)
{
return (y);
}
private:
int x,y;
};//end of point
//end of first namespace.
};
namespace anothernamespace//名字空间anothernamespace
{
class point
{
public:
point()
{
x=y=0;
}
void SetX(int xvalue)
{
x=xvalue;
}
int GetX(void)
{
return (x);
}
void SetY(int yvalue)
{
y=yvalue;
}
int GetY(void)
{
return (y);
}
void Reset()//唯一的不同之处;
{
x=y=0;
}
private:
int x,y;
};//end of point
//end of second namespace.
};
void main()
{
anamespace::point apoint;
apoint.SetX(10);
apoint.SetY(20);
cout<<"(x,y)=("<<apoint.GetX();
cout<<","<<apoint.GetY()<<")";
cout<<endl;
anothernamespace::point bpoint;
bpoint.SetX(10);
bpoint.SetY(20);
cout<<"(x,y)=("<<bpoint.GetX();
cout<<","<<bpoint.GetY()<<")";
cout<<endl;
bpoint.Reset();
cout<<"(x,y)=("<<bpoint.GetX();
cout<<","<<bpoint.GetY()<<")";
cout<<endl;
}
输出:
(x,y)=(10,20)
(x,y)=(10,20)
(x,y)=(0,0)
Press any key to continue
point可以正常的工作,程序加入了两句:
anamespace::point apoint;
anothernamespace::point bpoint;
这也就是名字空间的作用.
又如:
std::cout << "Hello, World!" << std::endl;
就是基于这个原因,
如果每次使用来自名字空间的类型声明一个变量时,
都必须使用作用域解析操作符.
这导致代码很冗长。
解决这个问题的办法就是在程序中放入一个using关键字.
比如程序开始的时候
using namespace std;
这样以后就只用写:cout << "Hello, World!" <<endl;
又比如要使用一个游戏引擎GameWorks2D,在程序开头处给出
using namespace gameworks2d;
如果空间中有一个mygame类型,就不必在整个代码中声明gameworks2d::mygame
在标准C++以前,都是用#include<iostream.h>这样的写法的,因为要包含进来的头文件名就是iostream.h。标准C++引入了名字空间的概念,并把iostream等标准库中的东东封装到了std名字空间中,同时为了不与原来的头文件混淆,规定标准C++使用一套新的头文件,这套头文件的文件名后不加.h扩展名,如iostream、string等等,并且把原来C标准库的头文件也重新命名,如原来的string.h就改成cstring(就是把.h去掉,前面加上字母c),所以头文件包含的写法也就变成了#include <iostream>。