在不同的编译单元中使用不同的编译标志编译相同的标头

时间:2015-10-28 16:27:40

标签: c++ compilation inline conditional-compilation

我遇到了一个奇怪的问题,这种问题破坏了我对编译单元封装的理解。

简而言之,我从标题中获得了一个共同的内联函数 我将它包含在2个不同的.cpp文件中,并使用不同的#define宏 但我最终在机器人编译单元中获得相同的实现。

COMMON.H:

#include <iostream>

inline void printA()
{
#ifdef YES
    std::cout << " yes" << std::endl;
#else
    std::cout << " no" << std::endl;
#endif
}

File1.h:

void print1();

File1.cpp:

#define YES
#include "Common.h"
#include "File1.h"

void print1()
{
    printA();
}

File2.h:

void print2();

File2.cpp

#include "Common.h"
#include "File2.h"
void print2()
{
    printA();
}

main.cpp中:

#include "File1.h"
#include "File2.h"

int main(int argc, char* argv[])
{

    print1();
    print2();

    return 0;
}

此示例的输出为:

yes
yes

我希望它是:

yes
no

那么,为什么两个编译单元都采用相同的实现方式? 常见功能甚至内联....

我怎样才能得到我的预期&#34;导致?

而且,为什么&#34;是&#34;实施选择?只是编译顺序问题?

顺便说一下,我在GCC 4.8和VS2012上得到了相同的结果

1 个答案:

答案 0 :(得分:3)

标准(此处为N4527)在 3.2一个定义规则 / 6

中说
  

类类型(第9条),枚举类型(7.2),内联函数可以有多个定义   外部链接(7.1.2),类模板(第14章),非静态函数模板(14.5.6),静态数据成员   类模板(14.5.1.3),类模板的成员函数(14.5.1.1)或模板特化   其中一些模板参数未指定(14.7,14.5.5),在程序中提供了每个定义   出现在不同的翻译单元中,并且定义满足以下要求。特定   然后,这样一个名为D的实体在多个翻译单元中定义   (6.1)

     

- D的每个定义应由相同的令牌序列组成;和

...

  

如果D的定义满足所有这些要求,   然后行为就好像有一个D的单一定义。如果D的定义不满足这些   要求,那么行为是未定义的。

因此将“是”替换为“否”是违反ODR的行为,导致未定义的行为。

对于获得“是”的结果,我可以猜测编译器随机选择一个函数,因为它们必须相同。

另一方面,如果您创建了函数static,则每个翻译单元中都会有不同的本地函数。