在不同的编译单元中使用不同的编译标志编译相同的 header
Compiling same header with different compilation flag in different compilation units
我遇到了一个奇怪的问题,它打破了我对编译单元封装的理解。
简而言之,我有一个从 header.
获得的通用内联函数
我将其包含到 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
那么,为什么在两个编译单元中采用相同的实现?
常用函数甚至内联....
如何获得 "expected" 结果?
而且,为什么选择 "yes" 实现?只是编译顺序的问题?
顺便说一句,我在 GCC 4.8 和 VS2012 上得到了相同的结果
标准(这里是N4527)在3.2一定义规则中说/6
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with
external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member
of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for
which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition
appears in a different translation unit, and provided the definitions satisfy the following requirements. Given
such an entity named D defined in more than one translation unit, then
(6.1)
— each definition of D shall consist of the same sequence of tokens; and
...
If the definitions of D satisfy all these requirements,
then the behavior is as if there were a single definition of D. If the definitions of D do not satisfy these
requirements, then the behavior is undefined.
所以用 "no" 替换 "yes" 是 ODR 违规,导致未定义的行为。
对于获得 "yes" 的结果,我可以猜测编译器会随机选择一个函数,因为它们 必须 相同。
另一方面,如果您创建函数 static
,您将在每个翻译单元中拥有不同的局部函数。
我遇到了一个奇怪的问题,它打破了我对编译单元封装的理解。
简而言之,我有一个从 header.
获得的通用内联函数
我将其包含到 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
那么,为什么在两个编译单元中采用相同的实现?
常用函数甚至内联....
如何获得 "expected" 结果?
而且,为什么选择 "yes" 实现?只是编译顺序的问题?
顺便说一句,我在 GCC 4.8 和 VS2012 上得到了相同的结果
标准(这里是N4527)在3.2一定义规则中说/6
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then (6.1)
— each definition of D shall consist of the same sequence of tokens; and
...
If the definitions of D satisfy all these requirements, then the behavior is as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.
所以用 "no" 替换 "yes" 是 ODR 违规,导致未定义的行为。
对于获得 "yes" 的结果,我可以猜测编译器会随机选择一个函数,因为它们 必须 相同。
另一方面,如果您创建函数 static
,您将在每个翻译单元中拥有不同的局部函数。