C ++命令模式

时间:2015-04-18 09:35:26

标签: c++

我试图实现类似命令模式的东西来控制具有相同界面的多个组件。每个组件都必须实现以下接口。

class ComponentInterface {
    public:
        virtual int start() = 0;
        virtual int stop()  = 0;
};

每个派生组件都会实现一些特定的方法。

class Led : public ComponentInterface {

    public:
        /**
         * Implements Interface methods
         */
        int start() { return 0; }
        int stop()  { return 0; }

    private:
        int setIntensity(int attrs[], int returns[]) {
            printf( "Set intensity called" );
            return 1;
        }

};

主要思想是每个子类将可调用成员函数存储在指针数组中,并且在ComponentInterface类中将实现一个可以根据命令的索引调用此函数的方法。

class ComponentInterface {
    public:
        ...
        // for storing the pointers
        int (ComponentInterface::*commandsArray[10])(int[], int[]);
        // to call the member functions
        int command(int commandId, int attrsList[], int responseList[]) {
            return (this->*commandsArray[commandId])(attrsList, responseList);
        }
}

class Led : public ComponentInterface {

    public:
        Led(float* ledIntensity) {
            // store the command in the array
            this->commandsArray[0] = (&Led::setIntensity);
         }

        // redefine the array for pointers of this subclass
        int (Led::*commandsArray[5])(int[], int[]);

};

我不熟悉C ++而且我不明白为什么它不起作用,我在调用存储的函数时遇到问题。

使用devC ++进行测试时,我遇到了分段错误。当我尝试在Visual Studio 2013(Visual C ++)中使用调试器进行测试时,它似乎在此行中

(this->*commandsArray[commandId])(attrsList, responseList);

this对象指向ComponentInterface对象而不是Led对象。

1 个答案:

答案 0 :(得分:2)

您的代码中有两件事是错误的:

  1. 你不能“覆盖基类变量”,这一行在派生类中没有意义

    // redefine the array for pointers of this subclass
    int (Led::*commandsArray[5])(int[], int[]);
    
  2. 此演员表错了

    this->commandsArray[0] = (&Led::setIntensity);
    

    它应该是

    this->commandsArray[0] = static_cast<int (ComponentInterface::*)(int*,int*)>(&Led::setIntensity);
    
  3. 无论如何,实现您想要的更简洁,更安全的方法如下:

    (免责声明:严重剥离,忽略讨论中不重要的一切)

    class ComponentInterface {
      ..
      std::vector<std::function<int (int[], int[])>> commandsArray;
    }
    

    Live Example

    然后,您可以使用不同的签名存储成员函数(绑定到正确的对象),并只使用组件中的ComponentInterface容器。