条件逻辑和跨平台处理
简而言之,条件预处理逻辑是关于使用宏定义使代码逻辑可用或不可用于编译。
三个突出的用例是:
- 不同的应用程序配置文件 (例如调试,发布,测试,优化)可以是同一个应用程序的候选者(例如,使用额外的日志记录)。
- 跨平台编译 - 单个代码库,多个编译平台。
- 利用通用代码库来实现多个应用程序版本 (例如软件的 Basic,Premium 和 Pro 版本) - 功能略有不同。
示例 a: 用于删除文件的跨平台方法(说明性):
#ifdef _WIN32
#include <windows.h> // and other windows system files
#endif
#include <cstdio>
bool remove_file(const std::string &path)
{
#ifdef _WIN32
return DeleteFile(path.c_str());
#elif defined(_POSIX_VERSION) || defined(__unix__)
return (0 == remove(path.c_str()));
#elif defined(__APPLE__)
//TODO: check if NSAPI has a more specific function with permission dialog
return (0 == remove(path.c_str()));
#else
#error "This platform is not supported"
#endif
}
像 _WIN32
,__APPLE__
或 __unix__
这样的宏通常由相应的实现预定义。
示例 b: 为调试版本启用其他日志记录:
void s_PrintAppStateOnUserPrompt()
{
std::cout << "--------BEGIN-DUMP---------------\n"
<< AppState::Instance()->Settings().ToString() << "\n"
#if ( 1 == TESTING_MODE ) //privacy: we want user details only when testing
<< ListToString(AppState::UndoStack()->GetActionNames())
<< AppState::Instance()->CrntDocument().Name()
<< AppState::Instance()->CrntDocument().SignatureSHA() << "\n"
#endif
<< "--------END-DUMP---------------\n"
}
示例 c: 在单独的产品构建中启用高级功能(注意:这是说明性的。通常更好的做法是在不需要重新安装应用程序的情况下解锁功能)
void MainWindow::OnProcessButtonClick()
{
#ifndef _PREMIUM
CreatePurchaseDialog("Buy App Premium", "This feature is available for our App Premium users. Click the Buy button to purchase the Premium version at our website");
return;
#endif
//...actual feature logic here
}
一些常见的技巧:
在调用时定义符号:
可以使用预定义符号调用预处理器(可选的初始化)。例如,此命令(gcc -E
仅运行预处理器)
gcc -E -DOPTIMISE_FOR_OS_X -DTESTING_MODE=1 Sample.cpp
以与将 #define OPTIMISE_FOR_OS_X
和 #define TESTING_MODE 1
添加到 Sample.cpp 顶部时相同的方式处理 Sample.cpp。
确保定义宏:
如果未定义宏并且比较或检查其值,则预处理器几乎总是默默地假定值为 0
。有几种方法可以解决这个问题。一种方法是假设默认设置表示为 0,并且需要明确地完成任何更改(例如,应用程序构建配置文件)(例如,默认情况下为 ENABLE_EXTRA_DEBUGGING = 0,设置 -DENABLE_EXTRA_DEBUGGING = 1 以进行覆盖)。另一种方法是使所有定义和默认值都明确。这可以通过 #ifndef
和 #error
指令的组合来实现:
#ifndef (ENABLE_EXTRA_DEBUGGING)
// please include DefaultDefines.h if not already included.
# error "ENABLE_EXTRA_DEBUGGING is not defined"
#else
# if ( 1 == ENABLE_EXTRA_DEBUGGING )
//code
# endif
#endif