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

时间:2019-04-18 14:36:02

标签: c++ macros c-preprocessor static-methods

我正在尝试编写一种软件,该软件的行为取决于是否应在软件中模拟某个组件或在实际硬件上执行该组件。但是,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()函数,并且仍然能够在预处理程序指令中引用它们?

2 个答案:

答案 0 :(得分:3)

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

处理器不理解#if的代码和参数,处理器必须能够处理它们,因此宏和文字。

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

一种解决方法是简单地使用if else

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

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

解决此问题的另一种方法是放弃宏。您可以使用模板。

或在某些类中包含宏相关的内容,并使用宏来更改该类的功能(这样,此宏将不会遍及您的代码)。

答案 1 :(得分:1)

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