类成员函数指针
我试图使用类功能(中断服务例程),类成员函数指针
void (ClassName::*fp)(void)=ClassName::FunctionName;
并将其附加到一个Arduino中断引脚使用具有以下类型输入的功能,但其不工作。
void attachInterrupt(int, void (*)(void),int);
我该如何做到这一点?中断服务例程(ISR)需要访问privat对象数据,所以我不能在类之外创建一个函数。
我的编译器错误:
注:我在寻找类中的解决方案,将接受表明我一个解决方案或显示我这是不可能的答案。
如果该函数不是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()
会的工作,因为结果是无法转换为一个函数指针。 Lambdas可以转换为函数指针,但前提是它们不捕获(而且这里的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>);
}
,她e是live example。
谢谢,非常翔实的答案。 – 2013-03-24 14:58:45
@FlyingSwissman:很高兴能帮到 – 2013-03-24 14:59:33
每个类成员函数都有一个隐含的第一个参数,即this
指针,因此您的方法实际上并不包含void paramter list - 它只接受一个参数 - 它被调用的实例。
好的,谢谢,这是有道理的,但不能解决我的问题。我能做的唯一事情就是公开对象数据并在对象之外创建一个ISR?还是有工作? – 2013-03-24 14:39:08
@AndyProwl好点。谢谢 – 2013-03-24 14:49:20
@FlyingSwissman:我在回答中提出了一个解决方法。不幸的是,当一个函数接受一个原始函数指针时,可以做的事情并不多。 – 2013-03-24 14:51:14
您可以使用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;
你得到一个错误。它有什么错误? – 0x499602D2 2013-03-24 14:30:01
我正在使用Visual Studio 2012编译器。我会把编译器错误置于我的问题中。 – 2013-03-24 14:31:36
抱歉,错误的编译器错误一开始,现在它的权利 – 2013-03-24 14:41:34