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方式与将#define OPTIMISE_FOR_OS_X和#define TESTING_MODE 1添加到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