将函数作为参数传递给派生类的父方法

时间:2016-04-26 14:15:39

标签: c++ inheritance

我有以下代码,其中execute()方法接受函数作为参数并执行它。然后,start()方法会调用execute()以运行method1()

class Test
{
  int Test::start(void)
  {
    execute(&Test::method1);
    return 1;
  }

  void Test::execute(void(Test::*func)(void))
  {
    (this->*func)();
  }

  void Test::method1(void)
  {
    //Do something...
  }
}

现在我想修改它,以便我实现以下目标:

  • 创建一个名为TestRunner的基类,并将execute()方法移至
  • Test继承自TestRunner,可以调用execute()方法运行其本地方法

我正在尝试以下方法,但我仍然不知道如何在execute()中指定方法参数,即我现在拥有的TestRunner::*func

class TestRunner
{
  public:
    TestRunner()
    {
       //Do something...
    }
  protected:
    void execute(void(TestRunner::*func)(void))
    {
      (this->*func)();
    }
}

class Test : TestRunner
{
    public:
      Test() : TestRunner()
      {

      }

      int start()
      {
        TestRunner::execute(&Test::method1);
        return 1;
      }

    private:
      void method1(void)
      {
        //Do something
      }    
}

如果我像这样编译代码,我显然会遇到这些错误:

  

没有匹配函数来调用' Test :: execute(void(Test :: *)())'

  

没有已知的转换参数1来自' void(Test :: )()'无效   (的TestRunner :: )()'

任何人都可以在这里指导我正确的方向,还是我需要做一些完全不同的事情来实现我的目标?

2 个答案:

答案 0 :(得分:0)

我在这里使用这个答案来提出解决方案:C++ Pointers to Member Functions Inheritance

创建一个回调类:

class Callback
{
    public:
        virtual ~Callback() { }
        virtual void doSomething()=0;
};

扩展回调类以定义函数的执行方式并使用模板:

template<class T>
class BCallback: Callback
{
    public:
        ~BCallback() { }
        BCallback(T *obj, void(T::*fn)()): obj_(obj), fn_(fn) { };

        void doSomething()
        {
            (obj_->*fn_)();
        }

    private:
        T *obj_;
        void(T::*fn_)();
};

在基类中使用回调对象:

class TestRunner
{
    protected:
        void execute(Callback *cb)
        {
            cb->doSomething();
        }
};

从派生类运行方法:

class Test: TestRunner
{
    public:
        int start()
        {
            BCallback<Test> cb(this, &Test::method1);
            this->execute(&cb);
            return 1;
        }

    private:
        void method1(void)
        {
            //Do something
        }   
};

答案 1 :(得分:0)

您可以像这样使用typedef

typedef void(Test::*Callback)(void);

然后,您可以使执行函数获取Callback类型的对象。它看起来像Test::execute(Callback)

调用时,请使用static_cast<>

Test tester;
tester.execute(static_cast<Callback>(&DerivedTest::someMethod));

示例Test::execute(Callback)实施:

Test::execute(Callback cb) {
    (this->*cb)();
}

通过这种方式,您可以避免编写整个两个新类(其中一个是模板,甚至是!)只是为了做一件简单的事情。作为奖励,您可以使用函数重载来获取Test::execute不同的函数签名。