C++ 条件逻辑和跨平台处理
示例
简而言之,条件预处理逻辑是关于使代码逻辑可用或不可用宏定义进行编译。
三种主要用例是:
不同的应用程序配置文件(例如,调试,发布,测试,优化)可以作为同一应用程序的候选对象(例如,带有额外的日志记录)。
跨平台编译-单个代码库,多个编译平台。
在多个应用程序版本(例如软件的基本版本,高级版本和专业版)中使用通用代码库-功能略有不同。
示例a:用于删除文件的跨平台方法(说明):
#ifdef _WIN32 #include <windows.h> //和其他Windows系统文件 #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__) //待办事项:使用权限对话框检查NSAPI是否具有更特定的功能 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 ) //隐私:我们仅在测试时才需要用户详细信息 << 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 //...这里的实际特征逻辑 }
一些常见的技巧:
在调用时定义符号:
可以使用预定义的符号(带有可选的初始化)来调用预处理器。例如,此命令(gcc-E仅运行预处理器)
gcc -E -DOPTIMISE_FOR_OS_X -DTESTING_MODE=1 Sample.cpp
的处理Sample.cpp方式与将#defineOPTIMISE_FOR_OS_X和#defineTESTING_MODE1添加到Sample.cpp顶部的方式相同。
确保定义了宏:
如果未定义宏并且对其值进行比较或检查,则预处理器几乎总是默默地将值假定为0。有几种方法可以解决此问题。一种方法是假定默认设置表示为0,并且任何更改(例如,对应用程序构建配置文件)都需要显式完成(例如,默认情况下ENABLE_EXTRA_DEBUGGING=0,将-DENABLE_EXTRA_DEBUGGING=1设置为覆盖)。另一种方法是使所有定义和默认值都明确。可以使用#ifndef和#error指令的组合来实现:
#ifndef (ENABLE_EXTRA_DEBUGGING) //如果尚未包含,请包含defaultDefines.h。 # error "ENABLE_EXTRA_DEBUGGING is not defined" #else # if ( 1 == ENABLE_EXTRA_DEBUGGING ) //code # endif #endif