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

Posted

技术标签:

【中文标题】C++使用模板类调用非静态成员函数【英文标题】:C++ Use template class to call non static member function 【发布时间】:2019-11-22 20:57:42 【问题描述】:

我正在尝试使用模板类来解决回调。我想为回调使用非静态成员函数。

我创建了两个类:

//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”的类。这个类有一个AbstractAction 的成员。当按下按钮时,它会调用exec() 函数。 exec() 是虚拟的,所以实际上调用了Action&lt;SomeClass&gt; 的函数。

现在我使用 Action 的对象创建一个类

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_-&gt;*class_func_ -> (class_obj_-&gt;*class_func_)() 【参考方案1】:

当你这样做时

class_obj_->*class_func_;

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

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

【讨论】:

我在网上找到的,没有括号。我在最后用括号试过了,但不是两者都试过。不,它正在工作。非常感谢。【参考方案2】:

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

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

【讨论】:

以上是关于C++使用模板类调用非静态成员函数的主要内容,如果未能解决你的问题,请参考以下文章

C++之静态

visual C++中error C2352是啥意思

visual C++中error C2352是啥意思

class中static总结-静态成员函数和静态成员变量

指向任何类类型的非静态成员函数的 C++ 函数指针

C++ static 静态成员总结