【发布时间】:2011-12-18 19:06:44
【问题描述】:
我是否违反了以下程序的单一定义规则?
// foo.hpp
#ifndef FOO_HPP_
#define FOO_HPP_
namespace {
inline int foo() {
return 1;
}
}
inline int bar() {
return foo();
}
#endif
//EOF
和
// m1.cpp
#include "foo.hpp"
int m1() {
return bar();
}
//EOF
和
// m2.cpp
#include "foo.hpp"
int m2() {
return bar();
}
//EOF
最后
// main.cpp
#include <iostream>
int m1();
int m2();
int main(int, const char* [])
{
int i = m1();
int j = m2();
std::cout << (i+j) << std::endl;
return 0;
}
// EOF
在上面,注意foo()是在匿名命名空间中定义的,所以我希望每个翻译单元m1.cpp和m2.cpp都会得到自己的版本,所以没有违反ODR。另一方面,bar() 只是一个普通的旧内联函数,它恰好调用了 2 个不同的 foos。所以它违反了 ODR,对吧?
更新:
以前我在foo 的定义中有宏,它改变了它返回的值,m1 和m2 在包含foo.hpp 之前对宏的定义不同。 (对于前面的示例,g++ 将生成一个二进制文件,输出 (i+j) 的值与您期望的值不同。)但实际上,即使 foo() 的主体是相同。
【问题讨论】:
-
我认为这清楚地说明了为什么在头文件中使用匿名命名空间或静态函数会带来麻烦:)
标签: c++ namespaces one-definition-rule