因此,我有一个内部功能指针的结构(称为tfunc)。我想创建一个该结构的实例,并将" tfunc"分配给特定函数。在这种情况下,我要分配的功能是" Fromatob(事件EVT)"。但是我得到了"不应该被忽略的无效价值"。我不明白为什么。
statemachine.h:
struct event{
int id;
QByteArray data;
};
typedef void (*transitionFuntionPtr)(event);
struct row{
event evt;
transitionFuntionPtr tFunc;
string output;
};
class StateMachine : public QObject
{
Q_OBJECT
public:
enum States{StateA, StateB, StateC};
explicit StateMachine(QObject *parent = 0);
int currentState;
struct event lastEvt;
multimap <int, row> transitionTable;
void EventHandler(struct event evt);
list<row> getEvtTable(struct event evt);
void setup();
void fromAtoB(struct event evt);
};
我如何在statemachine.cpp中分配功能指针:
StateMachine::StateMachine(QObject *parent) : QObject(parent)
{
struct row r;
struct event evt;
evt.data = "";
evt.id = 0;
r.evt = evt;
r.output = "GOT EVENT ID: " + evt.id;
r.tFunc = StateMachine::fromAtoB(evt); // ASSIGNMENT OF THE FUNCTION POINTER
}
错误:无效值不忽略,因为它应该是 r.tfunc = statemachine :: fromatob(evt);
谢谢:)
编辑:
所以向我指出,我应该将作业更改为
r.tFunc=StateMachine::fromAtoB;
但是现在我得到了这个错误:无法将" statemachine :: fromatob"从类型" void(statemachine ::)(event)"转换为'transitionFuntionptr {aka void(*)(event)}' r.tfunc = statemachine :: fromatob;
编辑#2:
我将函数" fromatob(事件evt)"制成静态,现在它进行了编译,但这不会使我无法从Statemachine创建对象?
您在这里有两个问题。
首先,正如其他两个答案所指出的那样,您实际上在尝试分配它时调用了功能。
由您的编辑指出的另一个问题是,您正在尝试将成员函数绑定到普通的C函数指针。这是行不通的,您需要使用C 成员功能指针。这样做的原因是,对成员函数的调用与呼叫的呼叫不同(或静态)函数不同:由于成员函数取决于对象状态,因此编译器必须隐式将指针传递到您的对象。想要调用成员函数作为隐藏参数。C 成员功能指针的问题是它们太可怕了。幸运的是,C 11解决了这个问题。
从C 11开始,有std::function
,当您需要传递函数y的内容时,应该是您的首选解决方案(为此,您必须使用#include <functional>
)。std::function
是一个模板,通过要分配给它的函数的签名进行参数化:
std::function<void(event)> func = &StateMachine::fromAtoB; // won't compile!
但是,等等,那也不起作用。还记得我们之前所说的关于编译器在成员函数呼叫上隐含将对象的指针隐含的指针吗?好吧,在这里我们必须明确地使事情起作用:
std::function<void(StateMachine*, event)> func = &StateMachine::fromAtoB;
StateMachine m;
Event ev;
func(&m, ev);
您可以通过将呼叫包裹在lambda中来隐藏函数调用取决于 StateMachine
对象的事实:
StateMachine m;
std::function<void(event)> func = [&m](event e) { m.fromAtoB(e); };
Event ev;
func(ev);
请注意,如果您让m
在func
之前死亡,这将爆炸可怕,因为Lambda保留了一个(非持有的)指针到m
,当m
被销毁时,它将悬挂。
this:
r.tFunc=StateMachine::fromAtoB(evt);
表示"调用fromAtoB()
,将其传递evt
,然后将返回值分配给r.tFunc
"。
您的意思是:
r.tFunc = StateMachine::fromAtoB;
不确定这是否会构建,因为这看起来像是对静态方法的引用,而fromAtoB()
是实例方法。与非类代码共享实例方法的指针可能是毛茸茸的,因为需要管理this
指针。
通常的解决方案是(是?)在类中提供静态方法,在实例方法中充当蹦床(但是现在有一个更好的解决方案,自写C 以来已经有几年了)。
在您的代码中进行语法进行
r.tFunc=StateMachine::fromAtoB(evt);
是将函数调用的返回值而不是功能指针的尝试。因此,编译器是正确的,因为函数返回类型为void
。
删除函数调用操作员,例如
r.tFunc = StateMachine::fromAtoB;