C++使用模板class调用非静态成员函数

C++ Use template class to call non static member function

我正在尝试使用模板 class 作为回调的变通方法。我想使用非静态成员函数进行回调。

我创建了两个 classes:

//First Class
class AbstractAction
{
public:
  AbstractAction() = default;
  virtual ~AbstractAction() = 0;

  virtual void exec() = 0;
};

//Second class
template<class T>
class Action: public AbstractAction
{
public:

  Action<T>(T* obj, void (T::*func)())
  : class_obj_(obj), class_func_(func) {}

  virtual void exec() {class_obj_->*class_func_;}

private:
  T * class_obj_;
  void (T::*class_func_)();

};

在我的代码中,我有一个名为 "Button" 的 class。此 class 有 AbstractAction 的成员。按下按钮时,它会调用 exec() 函数。 exec() 是虚拟的,所以实际上调用了 Action<SomeClass> 的函数。

现在我使用 Action

的对象创建了一个 class
class HardWork
{
public:
  HardWork()
  : action(this, &HardWork::workOnAction)  {}

private:
  void workOnAction() { /* do something using non static variables */ };

  Action<HardWork> action;
};

并且编译说:

In instantiation of 'void display::Action<T>::exec() [with T = HardWork]':
error: invalid use of non-static member function of type 'void (HardWork::)()'
   virtual void exec() {class_obj_->*class_func_;}
                        ^~~~~~~~~~

他为什么抱怨这个?他有一个指向 Hardwork 的实际对象的指针,所以他应该知道调用什么。其次,更重要的是我有什么办法。我不想使用静态解决方法。我有哪些选择?

当你做的时候

class_obj_->*class_func_;

您取消了对函数指针的引用,但实际上并未对它执行任何操作。您仍然需要像往常一样调用函数。您确实需要添加一些额外的括号来执行此操作,看起来像

virtual void exec() { (class_obj_->*class_func_)();}
                      ^^^^^get function^^^^^^^^^ ^
                                                 | call function 

为避免通过成员函数指针调用的语法混乱,自C++17起可以使用std::invoke

virtual void exec() {
    std::invoke(class_func_, class_obj_);
}