在MSVC C ++程序中,我有一部分代码要根据预处理器定义启用或禁用
// 1.h
#ifdef MYOPTION
//...
#endif
但我发现在多个编译单元中包含的.h文件中使用它是非常危险的,因为我很容易得到不一致的标题(我不想全局定义MYOPTION,因为它需要一个每次我改变时完成重新编译):
// 1.cpp
#define MYOPTION
#include "1.h"
// 2.cpp
#include "1.h"
当然,由于链接头包含,它比这个简化的例子要复杂得多。
有没有办法避免这种不一致,例如有没有太多努力的编译时错误?
我想过做#define MYOPTION 0
或1
,但后来我必须写一些像
#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif
看起来太复杂......也许有更好的选择?
答案 0 :(得分:2)
这样的事情:让1.h在obj中用不同的选项定义一个虚拟部分。这样,如果MYOPTION的使用不一致,链接器将发出警告。
1.H:
#ifdef MYOPTION
#pragma section("MYOPTION_GUARD",write)
#else
#pragma section("MYOPTION_GUARD",read)
#endif
namespace { __declspec(allocate("MYOPTION_GUARD")) int MYOPTION_guard; }
使用a.cpp中定义但未在b.cpp中定义的MYOPTION进行编译会产生此链接器警告(使用VC 2008):
b.obj : warning LNK4078: multiple 'MYOPTION_GUARD' sections found with different attributes (40300040)
一致的定义根本不会产生链接器警告。
答案 1 :(得分:1)
我认为你自己已经列出了大多数解决方案。我会使用最后的解决方案,但可能会略有不同:
#ifndef MYOPTION
#error ...
#endif
...
#if MYOPTION == 1
//...
#endif
因为#if MYOPTION == 1通常会在每个文件中出现多次。同样更清楚的是,MYOPTION是该文件的必备条件。
你说它“看起来太复杂了”,但我担心可能没有比这更“复杂”的解决方案。
答案 2 :(得分:0)
假设您确实需要使用定义,最好是通过编译器命令行定义它们,而不是源文件中的#define
。然后你的configure
脚本/ makefile / build进程设置一次定义,你保证它会在所有源文件中正确地达成一致。
答案 3 :(得分:0)
也许你想要的是创建一个单独的配置。
您可以转到构建 - > Configuration Manager 并创建一个新配置(与DEBUG,RELEASE分开)。创建新配置将允许您定义特定于该配置的预处理程序符号。
例如,使用名为“MyOption 1”的新配置,您可以添加预处理器定义MYOPTION = 1
。同样的事情伴随着MYOPTION = 2,3,......
每个配置都必须单独构建。
DEBUG和RELEASE是单独配置的示例; DEBUG定义_DEBUG
,RELEASE定义NDEBUG