條件邏輯和跨平臺處理

簡而言之,條件預處理邏輯是關於使用巨集定義使程式碼邏輯可用或不可用於編譯。

三個突出的用例是:

  • 不同的應用程式配置檔案 (例如除錯,釋出,測試,優化)可以是同一個應用程式的候選者(例如,使用額外的日誌記錄)。
  • 跨平臺編譯 - 單個程式碼庫,多個編譯平臺。
  • 利用通用程式碼庫來實現多個應用程式版本 (例如軟體的 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