我正在研究一个事件系统。基本上有任何成员可以插入的“插槽”。他们所需要的只是一个将要收听的事件名称和一个功能。由于存储了所有插槽,我必须将它们存储为类中的变量。
当函数放入SlotBase类时,该函数变得不可用。我想知道是否有办法在SlotBase类中存储时保留Slot类中的函数。
class SlotBase { };
// TC - Template Class
// TA - Template Arguments (types)
template <class TC, typename ...TA>
class Slot : public SlotBase {
public:
Slot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func);
}
template <int ...Is>
void SetSlot(TC* funcClass, void(TC::*func)(TA...), int_sequence<Is...>) {
function = std::bind(func, funcClass, placeholder_temp<Is>{}...);
}
void SetSlot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func, make_int_sequence<sizeof...(TA)>{});
}
std::function<void(TA...)> returnFunction(){
return function;
}
private:
std::function<void(TA...)> function;
};
//...
class RandomClass {
public:
void randomFunction(int a, float b, int c){ //do stuff };
}
//...
RandomClass randC;
SlotBase baseS;
Slot newSlot(&randC, &RandomClass::randomFunction);
baseS = newSlot;
//...
//Later on down the line when an event was found matching slot call slot function
baseS.returnFunction()(//Correct arguments go here - leaving this out (a lot more code));
我没有在'std :: bind'中包含整数序列的代码,因为它与问题无关。
我知道如果我在baseS
变量上使用Slot强制转换会给我结果,但我无法这样做,因为我不知道Slot会有的模板。
我看过许多类似的帖子说明baseS
指针(例如here),但我仍然不明白你将如何抓住这个功能。
答案 0 :(得分:0)
我认为你需要开始接受在某些时候如果你想使用多态对象,你需要在SlotBase
中创建一个虚函数。如果你想在使用函数之前在创建时回放你的类型,那么多态就没有意义,因为你已经将原始类型随身携带到了能够这样做的地方,所以为什么要在第一时间进行upcast呢? / p>
如果你真的需要upcast,那么你需要考虑一个RUNTIME解决方案来重新访问派生的功能。在这种情况下,这意味着您需要为信号创建一个通用接口,因此请尝试在SlotBase
中创建一个纯虚方法,该方法将打包一个未定义数量的参数,并在{{{{{}中实现该通用调用方1}}这样它就按顺序解包参数并用参数调用你的插槽。我不知道是否可以覆盖可变方法,这似乎是可疑的。否则,您必须使用boost :: any或其他东西来打包运行时集合中的参数。