9

最小代码:

// --------inline.h--------
struct X { 
  static inline void foo ();
};   
#ifdef YES
inline void X::foo () { cout << "YES\n"; }
#else
inline void X::foo () { cout << "NO\n"; }
#endif

// --------file1.cpp--------
#define YES    // <---- 
#include"inline.h"
void fun1 ()
{
  X::foo();
}

// --------file2.cpp--------
#include"inline.h"
void fun2 ()
{
  X::foo();
}

如果我们调用fun1()and fun2(),那么它们将分别打印YESand NO,这意味着它们引用了相同的不同函数体X::foo()

不管这是否应该编码,我的问题是:
这是一个定义明确的行为还是未定义的行为?

4

3 回答 3

13

是的,它是未定义的行为。

参考:

C++03 标准:

7.1.2 函数说明符 [dcl.fct.spec]
第 4 段:

内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义 (3.2)。[注意:在其定义出现在翻译单元之前,可能会遇到对内联函数的调用。] 如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。具有外部链接的内联函数在所有翻译单元中应具有相同的地址。外部内联函数中的静态局部变量始终引用同一个对象。外部内联函数中的字符串文字是不同翻译单元中的相同对象。

注:3.2 指的是单一定义规则,其中规定:

3.2 一个定义规则 [basic.def.odr]
第 1 段:

任何翻译单元不得包含一个以上的任何变量、函数、类类型、枚举类型或模板的定义。

于 2012-06-26T04:46:11.750 回答
7

不明确的。您违反了 ODR。

于 2012-06-26T04:38:58.760 回答
4

如果我们调用 fun1() 和 fun2(),那么它们将分别打印 YES 和 NO,这意味着它们指的是同一个 X::foo() 的不同函数体。

你试过了吗?具有不同的优化级别?

我得到 YES 和 NO、YES 和 YES,或 NO 和 NO,具体取决于优化级别和编译对象呈现给链接器的顺序。

不用说,这是未定义的行为。

于 2012-06-26T05:05:12.327 回答