Chinaunix首页 | 论坛 | 博客
  • 博客访问: 845967
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:10:38

最早是在下面的程序中发现的问题:

// a.cpp
struct foo
{
    void bar() { printf("foo::bar in a.cpp\n"); }
};

void testa()
{
  foo f;
  f.bar();
}

// b.cpp
struct foo
{
    void bar() { printf("foo::bar in b.cpp\n"); }
};

void testb()
{
  foo f;
  f.bar();
}

// main.cpp
int main( int argc, char** argv )
{
  testa();
  testb();

  return 0;
};

结果我发现这个程序居然输出:
foo::bar in a.cpp
foo::bar in a.cpp
先怀疑是编译器的bug, 不过很快否定了(因为编译阶段并不管具体链接的符号). 继而怀疑是链接器的bug, 但最后发现还是我的bug, 因为上面的代码实际上等价于

// test.h
struct foo
{
    inline void bar();
};

// a.cpp
#include "test.h"
inline void foo::bar() { printf("foo::bar in a.cpp\n"); }

void testa()
{
  foo f;
  f.bar();
}

// b.cpp
#include "test.h"
inline void foo::bar() { printf("foo::bar in b.cpp\n"); }

void testb()
{
  foo f;
  f.bar();
}

// main.cpp
int main( int argc, char** argv )
{
  testa();
  testb();

  return 0;
};

由于foo::bar是inline的, 所以允许每个编译单元有一个自己的实现, 但在链接阶段, 链接器是不可能发现这两个实现不同的(理论上可能,但工作量太大了), 所以它会假设实现相同(毕竟大家一般都把inline函数写在头文件中), 并把所有的引用指向同一个实现(如果分别指向本编译单元内部自有的实现肯定是错的, 考虑函数中定义了静态变量的情形), 这也就出现了本文中的问题. 如果foo::bar不是inline的, 则会有一个链接错误.
这里bar是作为一个成员函数出现的, 但它是非成员函数也有同样的问题, 所以结论就是: 不要在同一个名字空间中定义原型相同但实现不同的同名内联函数.

ps: 狗年最后一篇,祝大家新春愉快,万事如意,合家欢乐.

posted on 2007-02-14 11:31 局部变量 阅读(934)   

 re: inline 2007-04-24 10:38

粗一看,我以为是楼主不小心哪里弄错了。不过,我用VC8和gcc3.4.4都得出了这个结果。
对于:
int main( int argc, char** argv )
{
void testa( void );
void testb( void );

testa();
testb();

return 0;
}
我总觉得,他应该是得出正确的结果。从a.cpp的编写者,和b.cpp的编写者,他们其实可能都不知道对方的存在(假设),那么他们都应该是正确的。再说main.cpp,他只是需要外部连接testa和testb,那么更不知道有两个struct foo。我认为还是应该算编译器的bug。
当我去掉inline关键字时,VC8和gcc3.4.4都给出连接错。——这个是可以理解,它实现代价太高,所以没做。(严格来说,应该也算他们的bug,除非c++标准不允许这么做)

也就是说,结论是:
最好不要在同一个域里面,提供同名的符合,包括函数、变量、类名。如果他们可能会被外部引用,包括直接、间接。我之所以很难遇上,是因为我都已经很少使用extern。——大家熟悉的可能是函数、变量。

 re: 补充 2007-04-24 10:41

“我之所以很难遇上,是因为我都已经很少使用extern。”这句话写掉了一个字,还是用“我们”吧。^_^


--------------------next---------------------

阅读(414) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~