在不同的编译单元中使用不同的编译标志编译相同的头
Compiling same header with different compilation flag in different compilation units
我遇到了一个奇怪的问题,这个问题打破了我对编译单元封装的理解。
简而言之,我有一个常见的内联函数,它是从一个头中获得的
我将其包含在两个不同的.cpp文件中,并使用不同的#define
宏
但我最终在bot编译单元中得到了相同的实现。
Common.h:
#include <iostream>
inline void printA()
{
#ifdef YES
std::cout << " yes" << std::endl;
#else
std::cout << " no" << std::endl;
#endif
}
文件1.h:
void print1();
File1.cpp:
#define YES
#include "Common.h"
#include "File1.h"
void print1()
{
printA();
}
文件2.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
那么,为什么两个编译单元都采用相同的实现方式呢
公共函数甚至是内联的。。。。
我怎样才能得到"预期"的结果?
为什么选择"是"执行?只是汇编顺序的问题?
顺便说一句,我在GCC 4.8和VS2012 上得到了相同的结果
标准(此处为N4527)在3.2中规定了一个定义规则/6
类类型(第9条)、枚举类型(7.2)、内联函数可以有多个定义外部链接(7.1.2)、类模板(第14条)、非静态函数模板(14.5.6)、静态数据成员类模板的成员函数(14.5.1.1),或如果每个定义出现在不同的翻译单元中,前提是定义满足以下要求。鉴于这样一个名为D的实体在多个翻译单元中定义,那么(6.1)
--D的每个定义应由相同的令牌序列组成;和
如果D的定义满足所有这些要求,那么行为就好像有一个D的单一定义。如果D的定义不满足这些需求,则行为是未定义的。
因此,将"yes"替换为"no"是ODR违规行为,会导致未定义的行为。
对于得到"是"的结果,我可以猜测编译器随机选择一个函数,因为它们必须相同。
另一方面,如果您制作函数static
,则在每个翻译单元中都会有不同的本地函数。
相关文章:
- 即使使用调试编译标志,表达式也是"optimized out"
- 在 CMake 中添加全局编译标志
- 如何在 clang 的自动会议中检查支持编译标志
- CMake:如何在Visual Studio环境中将依赖于模式的编译标志传递给nvcc
- CMake:替换接口目标的编译标志
- GCC - 包含编译标志的宏
- 覆盖单个文件的编译标志
- 通过宏定义编译标志(C++11 和优化)
- 如何强制 Netbeans 只使用 -ggdb 编译标志而不使用它,同时在 Makefile-Debug.mk 中自动发
- 覆盖来自 R 的C++编译标志的系统默认值
- 是否可以在编译时间作为宏上检测GCC编译标志
- 如何将编译标志 -g 添加到 make 文件
- "-Bdynamic"编译标志有什么作用?
- 如何在cpp文件(C++)中设置编译标志
- Qmake 不使用 stdc++11 编译标志
- 如何在 CMake 文件中添加链接器或编译标志
- CMake-删除单个翻译单元的编译标志
- 添加 -fPIC 编译标志后"Recompile with -fPIC"错误仍然存在
- 在不同的编译单元中使用不同的编译标志编译相同的头
- c++链接和编译标志