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

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

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

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

#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)

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

不要为此使用 #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() 似乎没有任何作用。

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

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

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

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

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

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

解决它的其他方法是放弃宏。您可以使用模板。

或者在一些 class 中包含宏依赖的东西并使用宏来改变 class 功能(这样这个宏就不会遍布你的代码)。