类成员函数指针
Posted
技术标签:
【中文标题】类成员函数指针【英文标题】:Class member function pointer 【发布时间】:2013-03-24 14:28:55 【问题描述】:我正在尝试使用类函数(中断服务例程),
void (ClassName::*fp)(void)=ClassName::FunctionName;
并使用具有以下类型输入的函数将其附加到 Arduino 中断引脚,但这不起作用。
void attachInterrupt(int, void (*)(void),int);
我怎样才能做到这一点?中断服务例程(ISR)需要访问私有对象数据,所以我不能在类之外创建函数。
我的编译器错误:
ClassName.cpp : : In constructor 'ClassName::ClassName()':
ClassName.cpp : *)()'
ClassName.cpp : *)()' to 'void (*)()' for argument '2' to 'void attachInterrupt(uint8_t, void (*)(), int)'
注意:我正在课堂内寻找解决方案,并且会接受向我展示解决方案或向我展示不可能的答案。
【问题讨论】:
您是否遇到错误。这是什么错误? 我正在使用 Visual Studio 2012 编译器。我会将编译器错误放入我的问题中。 对不起,一开始编译错误,现在正确了 【参考方案1】:如果函数不是static
,则不能将其作为输入传递给接受非成员函数指针的函数。
考虑一个非static
成员函数有一个指向ClassName
的隐式指针作为它的第一个参数,它指向调用该成员函数的对象。
struct X
static void foo() // Does not have an implicit "this" pointer argument
void bar() // Has an implicit "this" pointer argument
;
int main()
void (*f)() = &X::foo; // OK: foo is static
void (*g)() = &X::bar; // ERROR! bar is non-static
在这里,即使std::bind()
也不起作用,因为结果不能转换为函数指针。 Lambda 可以转换为函数指针,但前提是它们是非捕获的(这里的 lambda 需要捕获对象以调用成员函数)。
因此,唯一(丑陋的)解决方法是拥有一个全局适配器函数,该函数调用对象上的成员函数,该对象可通过全局指针变量获得。全局指针变量在调用函数之前设置:
struct X
void bar()
;
void function_taking_a_function_pointer(void (*f)())
// Do something...
f();
X* pX = nullptr;
void bar_adapter()
pX->bar();
int main()
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function...
function_taking_a_function_pointer(bar_adapter);
如果您愿意,您可以通过将bar_adapter
转换为函数模板,并将指向成员函数的指针作为模板参数传递,从而稍微灵活一些:
template<typename T, void (T::*mf)()>
void adapter()
(pX->*mf)();
你会如何使用它:
#include <iostream>
struct X
void foo() std::cout << "X::foo()" << std::endl;
void bar() std::cout << "X::bar()" << std::endl;
;
void function_taking_a_function_pointer(void (*f)())
// Do something...
f();
X* pX = nullptr;
template<typename T, void (T::*mf)()>
void adapter()
(pX->*mf)();
int main()
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function(s)...
function_taking_a_function_pointer(adapter<X, &X::foo>);
function_taking_a_function_pointer(adapter<X, &X::bar>);
最后,这是live example。
【讨论】:
【参考方案2】:每个类成员函数都有一个隐式的第一个参数,即 this
指针,因此您的方法实际上不是带有 void 参数列表 - 它需要一个参数 - 调用它的实例。
【讨论】:
好的,谢谢,这是有道理的,但不能解决我的问题。我唯一能做的就是公开对象数据并在对象之外创建 ISR?还是有解决办法? @FlyingSwissman:我在回答中提出了一种解决方法。不幸的是,当函数接受原始函数指针时,可以做的事情并不多。【参考方案3】:您可以使用boost::function<>
或boost::bind<>
指向类成员函数:
# include <boost/function.hpp>
# include <boost/bind.hpp>
class FunctionClass
private:
double a_;
public:
FunctionClass (const double & a): a_(a )
double multWithA (const double & x) const return a_*x;
double operator ()(const double & x) const return a_*x;
;
FunctionClass myClass (2.0);
double x = 12.0;
boost :: function <double (FunctionClass *, double)> funcPtr , funcPtr1;
funcPtr =& FunctionClass :: multWithA;
funcPtr1 =& FunctionClass :: operator ();
std :: cout << myClass . multWithA (x) << std :: endl;
std :: cout << funcPtr (& myClass ,x) << std :: endl;
std :: cout << funcPtr1 (& myClass ,x) << std :: endl;
// Bind the function with the class instance
boost :: function <double (double)> funcPtrNew ;
funcPtrNew = boost :: bind (funcPtr ,& myClass ,_1);
std :: cout << funcPtrNew (x) << std :: endl;
【讨论】:
他不能,他必须传递一个void (*)(void)
函数指针。 (我不是 arduino 库的忠实粉丝。)
因为他要打电话给void attachInterrupt(int, void (*)(void),int)。以上是关于类成员函数指针的主要内容,如果未能解决你的问题,请参考以下文章