Chinaunix首页 | 论坛 | 博客
  • 博客访问: 174321
  • 博文数量: 43
  • 博客积分: 827
  • 博客等级: 准尉
  • 技术积分: 487
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-26 19:19
文章分类

全部博文(43)

文章存档

2015年(1)

2014年(1)

2013年(5)

2012年(36)

我的朋友

分类: C/C++

2012-01-26 19:31:01

对于全局变量和函数,他的连接属性是具有外链接(external linkage),所以在其他的.cpp文件中都用extern来告诉编译器,extern后面的东西在其他的.cpp中,在链接的时候进行地址重定位(address redirection),这样才能够在不同的.cpp中访问全局变量或者函数(对于函数只需要声明一下即可,不需要显示的用extern来声明)。而如果在工程中,两个.cpp出现了同样名字的变量或者函数,悲剧了,链接的时候会发生名称冲突。好,既然是外链接,用static限定为内链接(internal linkage),这是一种方法。
这里要介绍另一种方法,就是使用Anonymous namespace。对于namespace,他可以用来对于名字的可见Scope进行限定。通常情况下在一个namespace要访问另一个namespace中的标示符(identifier),必须使用using或者scope operator(XX::)。但是对于Anonymous namespace是没有名称的,所以在其他的.cpp中你不能使用using和scope operator去访问,也就是说Anonymous namespace中的标示符的可见性是文件级别(File-Scope)的。可以这样认为Anonymous namespace中的链接属性都是内链接。
个人认为使用Anonymous namespace比使用static更好,Anonymous namespace提供了一种语意:在该namespace中的定义都仅限于当前的.cpp文件中使用,比static更清晰明了。在The C++ Programming Language中,作者也建议尽量避免static使用,因为anonymous namespace可以取代他(这里的static不针对于函数级别的static)。
对于Anonymous namespace,在一个编译单元中编译器对他的处理是生成一个随机的名字,也就是在不同的经过预处理的.cpp文件中,Anonymous namespace具有不同的名字,这一点便于理解对他的使用(可参见The C++ Programming Language)。但是这一点也说明了,不能把一个声明写到.h中的Anonymous namespace中,而将实现放到.cpp的Anonymous namespace中:
  1. //header0.h

  2. namespace
  3. {
  4.     void func();
  5. };

  6. //header0.cpp

  7. namespace
  8. {
  9.     void func()
  10.     {
  11.     }
  12. };

  13. // other.cpp
  14. #include <header0.h>
对于other.cpp的预处理后的文件会是这个样子:
    1. //other.cpp after assemble
    2. // The inserted code of #include <header0.h>
    3. namespace
    4. {
    5.     void func();
    6. };

    7. // the other code of the other.cpp
如果在other.cpp中引用过了func(),在链接的时候将会有未定义错误,因为在header0.cpp和other.cpp两个各自对应的编译单元中,编译器生成的名称是不一样的。

所以对于Anonymous namespace尽量在.cpp中使用,个人也觉得他提供的语意也更容易在.cpp文件中体现。

其他:
外部链接(External Linkage): 对于在一个编译单元(Compiling unit)定义的全局变量或者函数在其他的编译单元中可以引用。
内部链接(Internal Linkage): 和上面的相反,只能在定义它的编译单元中引用。
编译单元(Compiling uint): 对于一个.cpp文件,经过预处理后生成的结果。也就是include的插入,macro替换,条件编译哪些代码不要,哪些要。

PS:
只要是有地址的东西就会有链接属性。对于const变量具有内部连接,在Global Scope, Named Namespace Scope,  Class Scope Static的变量和函数具有的是 外部链接。
在VS2003下面,他的编译器对匿名空间的支持不是很完善,可能会出现名称冲突。曾经遇到过一次,解决方法是对某一个.cpp从新生成一下.obj再链接。

Add 2012/11/18:
前两天遇到这样一个Bug:
在两个.h文件里面都前置声明了同样的类,然后在两个对应的.cpp文件都实现了这个类,但是生产的代码里面实际上只使用了其中一个Class,也就是两个.cpp里面实际上只有一个类被采用,并且编译器没有产生任何提示。
解决方法:
1: 改写类名字
2: 用Anonymous Namespace对这种类进行限定,但是这种方法会出现在头文件里面的Anonymouse Namesapace里的前置声明,这种情况可能会出现一些复杂的问题(在另外的.cpp文件包含这个.h文件,如果使用了这个前置声明类,则这个类你必须自己实现一个在Anonymouse Namesapace里的类)。
阅读(1180) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:不同基下的坐标变换

给主人留下些什么吧!~~