我正在尝试使用类函数(中断服务例程),
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)'
注意:我正在课堂上寻找解决方案,并接受向我展示解决方案的答案,或者告诉我这是不可能的。
答案 0 :(得分:6)
如果函数不是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>);
}
最后,这是一个live example。
答案 1 :(得分:2)
每个类成员函数都有一个隐含的第一个参数,即this
指针,所以你的方法实际上不是使用void参数列表 - 它需要一个参数 - 它被调用的实例。
答案 2 :(得分:0)
您可以使用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;