自动调用C++基类方法

Din*_*aiz 11 c++ methods class base-class

我正在尝试实现命令设计模式,但我遇到了一个概念问题.假设您有一个基类和一些子类,如下例所示:

class Command : public boost::noncopyable {
    virtual ResultType operator()()=0;

    //Restores the model state as it was before command's execution.
    virtual void undo()=0;

    //Registers this command on the command stack.
    void register();
};


class SomeCommand : public Command {
    virtual ResultType operator()(); // Implementation doesn't really matter here
    virtual void undo(); // Same
};
Run Code Online (Sandbox Code Playgroud)

问题是,每次()在SomeCommand实例上调用操作符时,我都想通过调用Command的register方法将*this添加到堆栈中(主要用于撤消).我想避免从SomeCommand :: operator()()调用"register",但要将它命名为automaticaly(someway ;-))

我知道当你构造一个像SomeCommand这样的子类时,基类构造函数被称为automaticaly,所以我可以在那里添加一个"register"调用.在调用operator()()之前,我不想调用它.

我怎样才能做到这一点?我想我的设计有些缺陷,但我真的不知道如何使这项工作.

Dav*_*eas 28

看起来您可以从NVI(非虚拟接口)习语中受益.在那里,command对象的接口没有虚拟方法,但会调用私有扩展点:

class command {
public:
   void operator()() {
      do_command();
      add_to_undo_stack(this);
   }
   void undo();
private:
   virtual void do_command();
   virtual void do_undo();
};
Run Code Online (Sandbox Code Playgroud)

这种方法有不同的优点,首先是您可以在基类中添加常用功能.其他优点是您的类的接口和扩展点的接口没有相互绑定,因此您可以在公共接口和虚拟扩展接口中提供不同的签名.搜索NVI,您将获得更多更好的解释.

附录:Herb Sutter 的原始文章,他介绍了这个概念(尚未命名)

  • 这就是为什么纯虚方法永远不应该进入公共接口的原因:你总是需要添加一些东西(记录,验证,预处理或后处理). (3认同)
  • @Dinaiz:很棒?告诉Sutter,我刚刚复制:)(顺便说一句:http://stackoverflow.com/users/297582/herb-sutter) (2认同)

Pat*_*ick 6

用两种不同的方法拆分运算符,例如execute和executeImpl(说实话,我真的不喜欢()运算符).Make Command :: execute non-virtual,Command :: executeImpl pure virtual,然后让Command :: execute执行注册,然后调用executeImpl,如下所示:

class Command
   {
   public:
      ResultType execute()
         {
         ... // do registration
         return executeImpl();
         }
   protected:
      virtual ResultType executeImpl() = 0;
   };

class SomeCommand
   {
   protected:
      virtual ResultType executeImpl();
   };
Run Code Online (Sandbox Code Playgroud)