如何在C++中宏 #define 静态方法调用?

How can I macro #define a static method call in C++?

本文关键字:静态方法 调用 #define 中宏 C++      更新时间:2023-10-16

我正在尝试编写软件,该软件可以根据某个组件是否应该在软件中模拟或在真实硬件上执行而具有不同的行为。但是,GCC 抱怨作用域解析运算符 (::) 不能在宏中使用,所以我的问题是:是否可以将宏定义为静态方法调用?

我的目标是能够使用另一个预处理器定义,选择使用所有真实组件 (0)、使用所有模拟组件 (1) 或混合使用真实组件和模拟组件 (2)。最后一种情况是我遇到这个问题的地方。在这种情况下,我想通过将其实现为静态方法来调用我正在"保护"的函数。这是我的方法:

#define SIM_CONF 2
#if SIM_CONF == 0
#define IS_HW_SIMULATED(name) false
#define IS_HW_REAL(name) true
#endif
#if SIM_CONF == 1
#define IS_HW_SIMULATED(name) true
#define IS_HW_REAL(name) false
#endif
#if SIM_CONF == 2
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)
#define IS_HW_REAL(name) SimConfig::isReal(name)
#endif
class SimConfig
{
public:
static bool isSimulated(const char* szName);
static bool isReal(const char* szName);
};

编辑:这是我如何在其他地方使用它的示例:

void PumpComponent::commandRevs(float revs)
{
#if IS_HW_SIMULATED("PumpComponent")
// do simulation procedure
#else
// do real hardware procedure
#endif
}

当我编译时,GNU Make 抱怨:

error: token "::" is not valid in preprocessor expressions
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)

是否有一些方法可以保护/封装isSimulated()isReal()函数,并且仍然能够在预处理器指令中引用它们?

问题是你如何使用这个宏。您已将其作为参数#if预处理器。

处理器不理解代码和参数#if一定是处理器可以处理的东西,所以宏和文字。

SimConfig::isSimulated是尚未定义的代码。在编译过程中会知道,所以预处理完成后。

修复它的一种方法是简单地使用ifelse

void PumpComponent::commandRevs(float revs)
{
if IS_HW_SIMULATED("PumpComponent") {
// do simulation procedure
} else {
// do real hardware procedure
}
}

对于编译器来说,这不是问题。 它会注意到这是常量,应该删除过时的代码。

修复它的另一种方法是放弃宏。您可以使用模板。

或者将依赖于宏的东西包含在某个类中,并使用宏来更改该类的功能(这样这个宏就不会散布到整个代码中)。

不要为此使用#if。只需编写普通代码:

void PumpComponent::commandRevs(float revs)
{
if (IS_HW_SIMULATED("PumpComponent")) {
// do simulation procedure
} else {
// do real hardware procedure
}
}

SIM_CONF为 0 或 1 时,编译器将删除其中一个分支,因为分支条件是编译时常量。它将在 2 岁时保留分支。

但是,我认为根本没有理由拥有IS_HW_SIMULATEDIS_HW_REAL宏。查看您发布的代码,似乎您只需要一个功能:SimConfig::isSimulated()

bool SimConfig::isSimulated(const char* szName)
{
#if SIM_CONF == 1
(void)szName; // supress "unused parameter" warning
return true;
#else
// Your normal implementation.
#endif
}

其余代码不需要使用任何宏:

void PumpComponent::commandRevs(float revs)
{
if (SimConfig::isSimulated("PumpComponent")) {
// do simulation procedure
} else {
// do real hardware procedure
}
}

SimConfig::isReal()似乎没有任何用处。