【问题标题】:Add commands to the instance manager with association to public method of two clases将命令添加到实例管理器并关联到两个类的公共方法
【发布时间】:2014-03-22 00:00:15
【问题描述】:

我希望能够将命令添加到管理器实例,并在执行这些命令时将这些命令与调用 A 类和 B 类的公共方法相关联。我知道为了实现这一点,类 Command 应该有一个指向类成员函数的指针,而不是常规的 function (void (T::*Handler)() 而不是 void(*Handler)() ),但我发现自己迷失了如何实现这一点。我有以下代码:

typedef void (*Handler)();

class Command {
    public:
        Command(char*, Handler);
    private:
        char* name;
        Handler handler;
};

class CommandManager {
    public:
        CommandManager();
        void addCommand(Command*);
        void execute(char* commandName);
    private:
        Command** commands;
}



// implementation, copy constructor and destructor should be ignored at this point since        they do
// not affect directly the question I'm trying to find an answer for.

我还有两节课。假设它们是 A 类和 B 类,都有返回类型为 void 的方法 并且没有参数。我还有 C 类,其中包含指向 A 和 B 的类型指针的成员变量:

class C {
    public:
     // some public stuff here
    private:
     A* a;
     B* b;  
     CommandManager* manager;
}

注意:引入继承和抽象类可能更容易,但这是我限制不使用的东西(不要问为什么:)),那么有什么方法可以做我想做的事吗?

【问题讨论】:

  • 当然,我的错误。帖子已编辑。但是,问题仍然有效。
  • 不相关,我不知道command 类的用途。似乎CommandManager 应该是名称到处理程序的映射:std::multimap<std::string, std::function<void()>>
  • 它就是这样做的。字符串和要执行的过程之间的映射。但是,也要尽量避免抽象数据结构和继承。
  • 我看到了以下问题:你们所有人都缺乏所有这些事情发生的背景。 Command 和 C 类的目的是从控制台读取用户输入,并成为更复杂系统的外观。所以我希望能够根据用户在标准输入中键入的内容调用不同的类方法。
  • 如果CommandManager 像我上面写的那样是map,它可以做到这一点。我不明白command 类的职责是什么。

标签: c++ templates pointers


【解决方案1】:

“最佳”解决方案:

typedef std::function<void()> Handler;
//std::function<void()> is the magic bit you were asking about

class Command {
    public:
        Command(const std::string& name, Handler) {}
    private:
        std::string name;
        Handler handler;
};

class CommandManager {
    public:
        CommandManager();
        void addCommand(std::unique_ptr<Command>);
        void execute(const std::string& commandName);
    private:
        std::vector<Command> commands;
};

然后functionoids变成这样

struct A { 
    void operator()() {std::cout << "A";}
};
Command  ACommand = {"A", A()}; 
//constructs a temporary A, 
//then a temporary std::function<void()> is constructed which stores the A
//then the Command stores this function.

struct B {
    void named_function() {std::cout << "B";}
};
B bobj;
Command  BCommand = {"B", std::bind(&B::named_function, &bobj)}; 
//bind constructs a functionoid binding the bobj as the "this" of the member function
//then a temporary std::function<void()> is constructed which stores the functionoid
//then the Command stores this function.

【讨论】:

    【解决方案2】:

    问题是this 指针隐式传递给每个成员函数。这使得A的函数签名与B的函数签名不同。

    不使用模板和继承,最简单的方法是将AB 的函数声明为static。那么,就没有this指针了,函数可以赋值给函数指针handler

    因为它可能不够强大,这里换一种方式,但我必须说它是一个kludge,使用继承真的会更好。

    定义

    typedef Handler void (*Handler)(void *);
    

    并按如下方式实现静态命令处理程序

    void A::doit(void *arg)
    {
      A *newthis = (A*)arg;
      newthis->UseMembersOfA();
    }
    

    【讨论】:

    • 最简单的方法应该是定义全局 A 和 B 指针,然后定义调用 A 和 B 方法的全局包装函数,但这是非常激进的解决方法。但是,模板是有效的解决方案,所以如果有的话会很好。
    • 那么 Mooing Duck 的解决方案似乎是可行的方法,但我仍在尝试同化 ;-)
    猜你喜欢
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多