C++命名空间

命名空间的定义

► 大型应用程序经常使用来自不同厂商的开发库,几乎不可避免会使
用相同的名字,也就是说一个库中定义的名字可能与其他库中的名
字相同而产生冲突,使得程序员不能组合各自独立的开发库到一个
程序中。
► 命名空间是用来限定名字的解析和使用范围的,它是C++开发大型
程序的工具之一。

► 命名空间的原理是将全局作用域划分为一个一个的命名空间,每个
命名空间是一个独立的作用域,在不同命名空间内部定义的名字彼
此之间互不影响,从而有效的避免了命名空间污染。

► 1. 定义命名空间

► 命名空间的定义形式为:
► 命名空间可以在全局作用域或其他命名空间内部定义,但不能在函
数、结构体或类内部定义,且要保证命名空间之间不会出现名字冲
突。

namespace 命名空间名 { {
……
} }

► 在命名空间作用域内,可以包含以下内容:
► ① 变量、对象以及它们的初始化。
► ② 枚举常量。
► ③ 函数声明以及函数定义。
► ④ 类、结构体声明与实现。
► ⑤ 模板。
► ⑥ 其他命名空间。

namespace A A{ { // 定义命名空间A A
const  int  PI= = 3.1415926; ; //const 常量
enum  tagDAYS{ { MON, , TUE, , WED, , THU, , FRI, , SAT, , SUN }; // 枚举常量
int i i, ,j j, ,k k= = 10; ; // 变量及变量的初始化
string str, , str2 ("hello"); // 对象及对象的初始化
int  max( ( int x x, , int y y ); // 函数声明
int  min( ( int x x, , int y y ){ return x x> > y?x: :y y ;} // 函数定义
template< < typename T T> > // 函数模板
int  compare( ( const T T& & v1, , const T T& & v2 ){ return  v1 == v2 ;}
template< < class T T> >  class  TComplex{ { // 类模板
public: :
TComplex (){}
void  setdata( ( T a, , T b ){x x= =a a; ;y y= =b b ;}
private: :
T r, ,i i; ;
};
namespace B B{ { // 嵌套的命名空间
int i i, ,j j, ,k k; ;
} }
} }

► (1)每个命名空间是一个作用域
► 定义在命名空间中的实体称为命名空间成员。命名空间中的每个名
字必须是该命名空间中的唯一实体,不同命名空间可以具有同名成
员。

namespace  A{ // 定义命名空间A A
int  fun,j;
int  fun(){return 10;} //错误,同一命名空间不能有相同的名字
} }
namespace  B{ // 定义命名空间B B
int  fun,j; //正确,不同命名空间可以有相同的名字
} }

► 在命名空间中定义的名字可以被命名空间中的其他成员直接访问,
命名空间外部的代码必须指出名字定义在哪个命名空间中,即作用
域运算符限定命名空间,形式为:
► 例如:

命名空间 :: 成员名
namespace  A{ // 定义命名空间A A
int  i=10;
void  output1(){cout<<i;} // 同一命名空间种直接引用成员i i
} }
void  output2(){cout<<A::i;} // 引用命名空间限定成员 A::i

► (2)命名空间可以是不连续的
► 命名空间可以在几个部分中分开定义,即命名空间是累积的。一个
命名空间可以分散在多个文件中。

namespace  A{ // 新创建一个命名空间A A
int  i;
} }
namespace  B{ // 新创建一个命名空间B B
int  i,j;
} }
namespace  A{ // 合并到前面的命名空间A A
int  j;
} }

► (3)接口和实现分离
► 命名空间可以不连续意味着可以做以下事情:
► 命名空间成员如果是类,可以将作为类接口的函数声明和对象
声明放在头文件中,使用这些命名空间成员的文件可以包含这
些头文件。
► 命名空间类成员的定义可以放在单独的源文件中。

► 例:

// complex.h  类接口放在头文件中
namespace A{ // 定义命名空间A A
class complex{
public:
complex(){}
void setdata(double a,double b);
private:
double r,i;
};
} }
// complex.cpp  类实现放在源文件中
namespace A{ // 合并到头文件中的A A
void complex::setdata(double a,double b){r=a;i=b;}
} }

► (4)定义命名空间成员
► 在命名空间内部定义的函数可以使用同一命名空间中定义的名字。
► 也可以在命名空间外部定义命名空间成员:

namespace A{ // sub 中直接使用 complex 类型
complex sub(complex& c1,complex& c2);
} }
A::complex A::sub(complex& c1,complex& c2);
{ { complex c;
c.setdata(c1.getr()+c2.getr(),c1.geti()+c2.geti());
return c;
} }

► (5)全局命名空间
► 定义在全局作用域的名字(任何类、函数或命名空间外部声明的名
字)是定义在全局命名空间中的。全局命名空间存在于每个程序中,
是隐式的。
► 可以用作用域运算符引用全局命名空间的成员:

int i=10; // 全局作用域
namespace A{ // 命名空间A A
void output(){ cout<<::i; } // 使用全局作用域成员i i
} }

► (6)嵌套命名空间
► 嵌套命名空间中的名字遵循名字规则:外围命名空间中声明的名字
被嵌套命名空间中同一名字的声明所屏蔽。

namespace outer{ // 外围命名空间
int i;
namespace inner{ // 嵌套命名空间
void f(){i++;}  // 使用的是 outer::i
int i; // 嵌套命名空间中的i i 屏蔽了 outer::i
void g(){i++;}  // 使用的是 inner::i
void h(){outer::i++;} // 使用的是 outer::i
} }
} }

► 2. 未命名的命名空间
► 定义命名空间时如果没有给出命名空间名字,称为未命名的命名空
间,定义形式为:

namespace  {
……
} }

► (1)未命名的命名空间中定义的名字可以直接使用,没有命名空
间名字来限定它们。
► (2)未命名的命名空间可以在给定文件中不连续,但不能跨越文
件,每个文件有自己的未命名的命名空间。本质上在一个文件中所
有未命名的命名空间会被系统用同一个标识符代替,且区别于其他
文件的标识符。

► 例:

namespace { int i; } // 假定未命名的命名空间标识为 unique
void f(){ i++; } //unique::i++
namespace A{
namespace {
int i,j; //A::unique::i 和 A::unique::j
}
void g(){ i++; } //A::unique::i++
} }
using namespace A;
void h(){
A::i++; //A::unique::i++
j++; //A::unique::j++
} }

► (3)未命名的命名空间专门用于声明局部于文件的实体。
► (4)未命名的命名空间中定义的名字只在包含该命名空间的文件
中可见。如果另一文件包含一个未命名的命名空间,两个命名空间
不相关,可以定义相同名字的实体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YULIU_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值