C++学习笔记-命名空间

命名空间

命名空间或者叫名字空间(名字就是namespace)是为了在大型项目中防止标识符冲突才引入的,实际上就是可以由用户命名的作用域

touzani的专栏的这篇C++ 命名空间namespace,我觉得写的很明白(不敢说好坏,因为我也是抱着学习的态度读技术博客),该部分大量参考了这篇博文。

与命名空间相关的概念:
  • 声明域(declaration region)—— 声明标识符的区域。如在函数外面声明的全局变量,它的声明域为声明所在的文件。在函数内声明的局部变量,它的声明域为声明所在的代码块(例如整个函数体或整个复合语句)。

  • 潜在作用域(potential scope)—— 从声明点开始,到声明域的末尾的区域。因为C++采用的是先声明后使用的原则,所以在声明点之前的声明域中,标识符是不能用的。即,标识符的潜在作用域,一般会小于其声明域。

  • 作用域(scope)—— 标识符对程序可见的范围。标识符在其潜在作用域内,并非在任何地方都是可见的。例如,局部变量可以屏蔽全局变量、嵌套层次中的内层变量可以屏蔽外层变量,从而被屏蔽的全局或外层变量在其倍屏蔽的区域内是不可见的。所以,一个标识符的作用域可能小于其潜在作用域。C语言中文网的解释更干脆:”我们把变量在程序中可以使用的有效范围称为变量的作用域。”

原来C++标识符的作用域:全局作用域、块作用域、类作作用域。如果要按范围大小排个序的话,我的理解是这样:

块作用域 < 类作用域 < 全局作用域
而命名空间介于类作用域与全局作用域之间。

命名空间可以是全局的,也可以位于另一个命名空间之中,但是不能位于类和代码块中。所以,在命名空间中声明的名称(标识符),默认具有外部链接特性(除非它引用了常量),也就是具有全局作用域,但并不是全局可见的。

在所有命名空间之外,还存在一个全局命名空间,它对应于文件级的声明域。因此,在命名空间机制中,原来的全局变量,现在被认为位于全局命名空间中。

定义命名空间:

有名的命名空间:

namespace 命名空间名 {
   声明序列可选
}

无名的命名空间:

namespace {
    声明序列可选
}

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

例如:

namespace Outer // 命名空间Outer的定义
{ 
    int i; // 命名空间Outer的成员i的内部定义
    namespace Inner // 子命名空间Inner的内部定义
    { 
        void f() // 命名空间Inner的成员f()的内部定义,其中的i为Outer::i
        { 
            i++; 
        } 
        int i;
        void g() // 命名空间Inner的成员g()的内部定义,其中的i为Inner::i
        { 
            i++; 
        } 
        void h(); // 命名空间Inner的成员h()的声明
    }

    void f(); // 命名空间Outer的成员f()的声明
    // namespace Inner2; // 错误,不能声明子命名空间
}

void Outer::f() // 命名空间Outer的成员f()的外部定义
{ 
    i--;
} 
void Outer::Inner::h() // 命名空间Inner的成员h()的外部定义
{ 
    i--;
} 
// namespace Outer::Inner2 // 错误,不能在外部定义子命名空间
// { 
//      /*……*/
// } 

注意:

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

也不能直接使用“命名空间名::成员名 ……”定义方式,为命名空间添加新成员,而必须先在命名空间的定义中添加新成员的声明。

另外,命名空间是开放的,即可以随时把新的成员名称加入到已有的命名空间之中去。方法是,多次声明和定义同一命名空间,每次添加自己的新成员和名称。例如:

namespace A
{
   int i;
   void f();
} // 现在A有成员i和f()

namespace A 
{
    int j;
    void g();
} // 现在A有成员 i、f()、j和g()
使用命名空间:
  1. 使用作用域限定符: ::
  2. 使用using声明机制: using 名称空间::实体名
  3. 使用using编译指令:using namespace 名称空间名;

至于using声明语句或编译指令将该实体的可见域扩展到什么程度,这取决于using语句的书写位置,换言之,这取决于using语句的可见域:

#include <iostream>
#include <string>
using std::string; // using声明在全局区域,string全局可见(不考虑局部同名覆盖时)

void Display(const string text)
{
//    using namespace std; // 也可以,std中的所有实体仅在该块作用域内可见
    using std::cout;  // using声明在局部区域,string仅该块作用域内可见
    using std::endl;
    cout << text<< endl;
}

int main()
{
    string str = "code the world!";
    Display(str);
//    cout << str << endl; // 有效但不可见,可以通过std::cout、std::endl来使用
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值