跳转到内容

更多 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)
[编辑 | 编辑源代码]
华夏公益教科书