跳轉到內容

更多 C++ 慣用法/內聯保護宏

來自華夏公益教科書,開放的書籍,開放的世界

內聯保護宏

[編輯 | 編輯原始碼]

使用編譯器命令列宏定義開關方便地控制函式的內聯性。

也稱為

[編輯 | 編輯原始碼]

為了除錯目的,通常需要關閉整個程式中函式的內聯。但是對於釋出版本,行內函數是可取的。這表明需要一種快速的方法來開啟/關閉內聯性,具體取決於需要。此外,此類函式應在內聯時定義在標頭檔案中,否則應在原始碼 (.cpp) 檔案中定義。如果非行內函數位於標頭檔案中,則幾乎總是會導致函式的多個定義。另一方面,如果行內函數不在標頭檔案中,則編譯單元將找不到它們。在這兩種情況下,連結器都會丟擲錯誤。

因此,一種靈活的內聯方式通常是可取的,但 C++ 語言不支援這種方式,除非使用一些宏技巧。內聯保護宏慣用法實現了這一點。

解決方案和示例程式碼

[編輯 | 編輯原始碼]

解決方案是將所有行內函數放在一個名為 .ipp 的單獨檔案中,並用宏 INLINE 裝飾每個函式。標頭檔案和實現檔案照常建立,.ipp 檔案根據是否需要內聯,選擇性地包含在兩個檔案(標頭檔案或實現檔案)中的一箇中。下面給出了一個類 Test 的示例。

// test.ipp file
INLINE void Test::func()
{}


// test.hpp file
#ifndef MYPROJECT_TEST_H // Note include guards.
#define MYPROJECT_TEST_H 

class Test
{
  public:
    void func();
};

#ifdef MYPROJECT_INLINE_ENABLED
#define INLINE inline // Define INLINE as inline (the keyword)
#include "test.ipp"   // It is included only when MYPROJECT_INLINE_ENABLED is defined, i.e. inlining is enabled.
#endif

#endif  // MYPROJECT_TEST_H


//test.cpp file
#include "test.hpp" // Include header file as usual.

#ifndef MYPROJECT_INLINE_ENABLED
#define INLINE      // INLINE is defined as empty string
#include "test.ipp" // It is included only when MYPROJECT_INLINE_ENABLED is NOT defined, i.e. inlining is disabled.
#endif

使用 Include Guard Macro 的效果是,根據 MYPROJECT_INLINE_ENABLED 是否定義,test.ipp 將被 #included 在 test.cpp 或 test.hpp 中。當它與 test.cpp 合併時,函式不會被內聯,因為 INLINE 被定義為空字串。另一方面,當 test.ipp 與 test.hpp 合併時,INLINE 被定義為 inline(關鍵字)。

現在,剩下的就是根據需要定義 MYPROJECT_INLINE_ENABLED 宏。通常,所有現代 C/C++ 編譯器都允許在命令列定義宏。例如,要在 gcc 上使用內聯編譯上述程式,將引數 -DMYPROJECT_INLINE_ENABLED 選項新增到編譯命令列。如果未定義此類宏,則函式將自動被視為非內聯,程式可以正常編譯。

已知用途

[編輯 | 編輯原始碼]
  • ACE(自適應通訊環境)
  • TAO(ACE ORB)
[編輯 | 編輯原始碼]
華夏公益教科書