所以,我先做了一个合理数量的谷歌搜索,但所有的解决方案似乎都过于复杂。所以,我想我会在这里问这个任务是否真的需要我遇到的那种方法...
所以,说我有一个Event
课程。我希望它有一个time
变量和一个functionToExecuteAtTime
函数指针/变量/魔法代码片段,它允许我将任何旧函数传递给这个类。
此外,我希望在优先级队列中保存的事件按时间顺序排列事件并执行它们“携带”的功能。但是暂时忘掉了这个
像这样......
class Agent
{
public:
int id;
float cash;
Agent::Agent
{
cash = 100;
}
}
class uberSystem
{
public:
float assets;
int supplyOfDeadlyPoison;
float poisonCost;
std::vector<Agent> agents;
uberSystem::uberSystem
{
assets = 100000;
supplyOfDeadlyPoison = 100000;
poisonCost = 8;
for(int i = 0; i < 100; i++)
{
Agent newAgent;
newAgent.id = i;
agents.push_back(newAgent)
}
}
};
class Event
{
public:
int time;
SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS myFunction;
Event::Event(int t, SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS func)
{
time = t;
myFunction = func;
}
}
int uselessFunction()
{
return 42;
}
void buyPoisonAndKillAgent(Agent &myAgent, uberSystem &mySystem)//obviously not good...
{
myAgent.cash -= mySystem.poisonCost;
mySystem.assets += mySystem.poisonCost;
mySystem.agents.erase(mySystem.agents.begin()+myAgent.id);
mySystem.supplyOfDeadlyPoison -= 1;
}
int main()
{
uberSystem newSystem;
// Event newEvent(100, uselessFunction());//make a new event
Event newEvent(100, buyPoisonAndKillAgent(newSystem.agents[5], newSystem));
newEvent.myFunction;//run the bloody function
return 0;
}
好的,所以我现在打字就像是非常一厢情愿的想法。那么,我怎样才能做到这一点?函数指针是要走的路吗?还是有一些更好的方法,我有办法找不到?
哦,显然我确实有std::function
可用......我一直都不在石器时代!
谢谢!
答案 0 :(得分:2)
你可以有一个Base类事件(由@EdHeal提出),然后有一个模板子类存储你的函数指针:
class Event {
public:
int time;
Event(int t) : time(t) {}
virtual ~Event(){}
virtual void myFunction() = 0;
};
template<typename TFunc>
class TEvent : public Event {
public:
TFunc func;
TEvent(int t, TFunc f) : Event(t), func(f) {}
void myFunction() { func(); }
};
template<typename TFunc>
auto_ptr<Event> make_event(int time, TFunc func) {
return std::auto_ptr<Event>(new TEvent<TFunc>(time,func));
}
使用辅助函数make_event
,可以轻松调用并自动推断类型:
void useless() {std::cout << "Func A";}
struct functor {
void operator()() {std::cout << "Functor B";}
};
struct paramFunctor {
paramFunctor(int x, double y): result(0), m_x(x), m_y(y){}
void operator()() {
std::cout << "Params: x:" << m_x << ", y:" << m_y << "\n";
}
long long result;
private:
int m_x;
double m_y;
};
int main() {
auto_ptr<Event> e1 = make_event(10,useless);
auto_ptr<Event> e2 = make_event(100,functor());
auto_ptr<Event> e2 = make_event(100,paramFunctor(1,2.0));
// your code goes here
e1->myFunction();
e2->myFunction();
e3->myFunction();
return 0;
}
当然,如果可以访问C ++ 11(或TR1或者boost),根本不需要所有这些(正如其他答案所描述的那样)
答案 1 :(得分:1)
为什么不这样做
class Event {
private:
int time;
public:
Event(int t) : time(t) { }
virtual void DoEvent() = 0;
};
class MyEVent: public Event {
public:
MyEvent(int t) : Event(t) { }
void DoEvent() { std::cout << "Event called" << std::endl;
};
然后
int main() {
MyEvent e(100);
e.DoEvent();
return 0;
}
这看起来更简单,您可以随意添加活动所需的任何数据。
对于列表,您使用Event
指针,例如Event *e = new MyEvent(100)
答案 2 :(得分:1)
持有泛型函数或闭包的最简单方法是使用std::function
;在没有C ++ 11 boost::function
的情况下,它是一个很好的占位符。
这会产生:
class Event {
public:
private:
std::time_t time;
boost::function<void()> function;
}; // class Event
请注意,函数的签名需要精确处理:void()
是一个不带参数且不返回任何内容的函数。
另外,请注意,只要其中一个operator()
与预期签名匹配,就可以使用任意谓词,仿函数类或lambdas。