C++问题:关于匿名命名空间

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++问题:关于匿名命名空间相关的知识,希望对你有一定的参考价值。

匿名命名空间有什么用?怎样才能使用匿名命名空间里的标识符?

主要是为了团体使用时的重名问题.我们举例说明,假如你找一个学校找小明这个人.那么这个叫小明的人可能有好几个,如果你可以确定小明在3班,那么就可以排除掉别的班的小明了.命名空间也就是班级.小明也就是你的变量或函数.现在明白了吧?
使用命名空间里的东西,要使用双冒号::
你也可以解放命令空间,using namespace 空间名字;
在文件头加入这句.这样就可以把空间名字处的空间内容解放出来,之后再使用就不用加::
定义命令空间是
namespace Name

int x;

这样以来,你如果要在别的地方用这个X变量,就要Name::x=5;这样才可以用.
using namespace Name;
这样后,就可以直接 
x=5;

CA少看两个字,匿名命名空间 也就是在申请的时候不写名字,由系统自动分配.匿名名字空间具有一个很有用的特性,那就是,对于不同的编译单元(cpp文件),“同一个”匿名名字空间中的对象,会被当作不同的实体。而这个特性和全局的static修饰是一致的追问

能对匿名命名空间解释详细一点吗?如果我要用匿名命名空间里的标识符我要怎么用?

追答

先谈谈全局变量.通常定义一个全局变量,如果没有static约束,那么这个变量在被编译的时候,生成的是public的符号.链接的时候,外部的代码如果有了extern声明,那么外部的代码就可以访问这个全局变量.如果加了static声明的全局变量,那么这个全局变量是私有的,只能在当前的编译单位(.c/.cc等)中访问,外部是不可见的.

//test1.cpp

int g_int;

//test2.cpp

extern int g_int;

void f()

g_int = 1;


如上,test2引用了test1中的变量.当然,这样生成的目标文件,实际上test2.obj对test1.obj是有依赖的.否则链接的时候找不到符号.比如通常的静态链接库,就是这样,编译好了lib之后,头文件里面有函数声明,如果有变量,那么需要声明为extern,供别人使用.

如果把上面的test1.cpp中的int g_int;加上static修饰,那么链接时,提示test2中引入的符号( _g_int )找不到.

上面的情况对于C和C++都是适用的.C++另外有一种匿名的命名空间,来保证生成的符号是局部的,这样对于匿名空间中的变量等,外部都是不可见的.

//test3.cpp

static void bar()

namespace //匿名的命名空间

float bar2;
int foo;


//test4.cpp
extern int foo;
extern void bar();
extern float bar2;
int main()

bar(); //外部的bar()被声明为static,这里链接不到符号.不能访问
bar2 = 0.1f; //外部的匿名空间哩,这里也不能访问.
foo = 0xFF;
return 0;
;//如果将test4的目标和test3的目标进行链接,实际上是找不到这些符号的.链接会失败.

匿名的命名空间是C++的特性,相对于C的static声明来说,可以在匿名的空间里面声明很多变量和函数,这样可以省去了对每个变量和函数添加static声明.
实质上匿名空间的功能跟static声明是一样的.

参考技术A c++里因为标准库非常的庞大,所以程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。为了避免这种情况所造成的名字冲突,就把标准库中的一切都放在名字空间std中。当然可以自己定义自己的名字空间。
一句话讲,名字空间是用来区分同名的类或者函数的。

由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下:
std::cout << std::hex << 3.4 << std::endl;
2、使用using关键字。
using std::cout;
using std::endl;
以上程序可以写成
cout << std::hex << 3.4 << endl;
3、最方便的就是使用using namespace
std;这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写:
cout << hex << 3.4 << endl;
参考技术B namespace A//A是可以使用的名字

要访问的话用两种方法
1.在使用之前使用这句话 using namespace A;
2.可以使用A::加上要访问的里面的东西

C++:在匿名命名空间中声明函数原型的正确方法是啥?

【中文标题】C++:在匿名命名空间中声明函数原型的正确方法是啥?【英文标题】:C++: what is the proper way of declaring function prototype in anonymous namespace?C++:在匿名命名空间中声明函数原型的正确方法是什么? 【发布时间】:2015-09-01 04:44:25 【问题描述】:

如果我以明显的方式在 .h 中声明它:

namespace <named_namespace> 
    namespace 
        …
        <type> <function>(<parameters>);
        …
    

并将其实现放到.cpp中,会出现编译错误:

'&lt;type&gt; &lt;named_namespace&gt;::anonymous::&lt;function&gt;(&lt;parameters&gt;)' should have been declared inside &lt;named_namespace&gt;

如果不将函数的实现放在单个文件中,是否可以避免此错误?目前我使用关键字static 代替,但它会产生多个烦人的警告:

'&lt;type&gt; &lt;named_namespace&gt;::&lt;function&gt;(&lt;parameters&gt;)' declared 'static' but never defined

据我了解,只能通过将功能保存在单个文件(头文件或源文件)中来禁用它。

欢迎使用交叉编译器解决方案(如果有)。

或者也许将头文件分成“公共”和“私有”部分更有效?

【问题讨论】:

如果这个函数是私有的,为什么要把它放在头文件中? 为什么要在匿名命名空间中声明?正如编译器所说,它不应该是。你想完成什么? 未命名命名空间的目的是避免其他翻译单元的可见性,因此声明它是无稽之谈。看到这个问题:***.com/questions/357404/… 这看起来像xy problem,你想做什么?将匿名命名空间放在头文件中几乎没有意义。对于静态函数也是如此。如果它只是定义并且只能从一个文件中使用,为什么要在多个文件中声明它? 好吧,我在 C++ 中缺乏静态类功能,所以我尝试通过命名空间来实现它。现在我发现这是不可能的。 【参考方案1】:

您不能拥有跨翻译单元工作的匿名命名空间,因此将匿名命名空间放在 .h 中不会像您预期的那样工作。在每个翻译单元 (.cpp) 中,该命名空间被分配了一个不同的唯一名称。

单独的声明和定义是可能的,但只能在该命名空间内:

namespace 
    void func();


…

namespace 
    void func()
    
        …
    

【讨论】:

以上是关于C++问题:关于匿名命名空间的主要内容,如果未能解决你的问题,请参考以下文章

C++:在匿名命名空间中声明函数原型的正确方法是啥?

关于匿名命名空间和内部链接的标准是啥?

关于iostream和c++命名空间

C++ 项目相关知识命名空间

在 Visual Studio 中检查内存转储时匿名命名空间中的符号

私有静态成员函数或匿名命名空间中的自由函数?