-
19-08-2019 - |
题
typedef void (FunctionSet::* Function)();
class MyFunctionSet : public FunctionSet
{
protected:
void addFunctions()
{
addFunction(Function(&MyFunctionSet::function1));
}
void function1()
{
// Do something.
}
};
该addFunction方法增加了功能的一个列表中的基类,
然后可以列举的呼吁所有功能。
是否有任何方法来简化(小打字工作)的增加的职能?
解决方案
看起来喜欢你分配了一件功能的指针指向一个功能衍生出类成员的功能指向一个功能的基类。嗯,这是禁止的,因为它打开了一个洞类型的系统。它涉及在一个惊喜(至少对我来说,我第一次听到的那)。阅读 这个答案 对于为什么。
来回答你的实际问题的-我会做 addFunction
一个模板:
void addFunctions() {
addFunction(&MyFunctionSet::function1);
}
改变 addFunction
在基类:
template<typename Derived>
void addFunction(void(Derived::*f)()) {
myFunctions.push_back(static_cast<Function>(f));
}
更好的使用 static_cast
, 因为它会告诉你如果 Derived
实际上不是来自 FunctionSet
.
其他提示
你能解释一下你正在试图这样做是为了达到什么样的?
这似乎是一个相当不好的设计,不能你有一个抽象类(“C ++接口”),例如,其具有纯虚功能1,子类可计算每个实现的“可计算”,然后有MyFunctionSet维持设定的可计算?
您是否能使用函数指针的具体原因是什么?
所以,我倾向于开放的不同意,有点。
如果您正在实现Observer模式,你想要的是能够说:
“当对象X确实Y,我想执行代码Z”。
对一个抽象类,纯粹基于一种方法去是不是这样做的最佳方式。需要一个单独的类(特别是在C ++)对于每个事件处理程序是矫枉过正。如果你来自Java的,这就是他们做的一切。但是,Java有2个功能,使这只是有点烦:匿名类,和“实例”成员类。这使您可以定义多个处理程序在同一个类中的多个事件。你有“类{”前缀的方法,但你可以做到这一点。
C ++不具有任一匿名类或“实例”成员类。这使得使用事件的抽象类更繁琐,如果你有需要共享状态多个处理程序。你要做封代用手等价,这可以得到相当刺激性的很快。
.NET使用用于事件处理的代表,它们基本上类型安全函数指针。他们使代码处理事件非常直截了当。不像在C ++函数指针,然而,一个代表结合成员函数指针和静态函数指针。基本上,它可以咖喱任何成员函数的“这个”参数,留下一个函数指针,看上去就像一个静态函数指针。这意味着,处理该事件的对象的类型不是事件“接口”的一部分。这使得它非常灵活。
,因为“这种”型最终被函数指针型的一部分,从而限制了您的处理程序只在当前类中出现不能做直接使用C ++成员函数指针。
有C ++的最佳解决方案是在两者之间的混合体。你需要的是一个通用的接口是这样的:
class EventHandler
{
public:
virtual void Handle() = 0;
};
和然后的成员函数的实现这样
template <class T>
class MemberFuncEventHandler : public EventHandler
{
public:
MemberFuncEventHandler(T * pThis, void (T::*pFunc)()) : m_pThis(pThis), m_pFunc(pFunc)
{
}
void Handle()
{
(m_pThis->*m_pFunc)();
}
private:
T* m_pThis;
void (T::*m_pFunc)();
};
template <class T>
EventHandler * Handler(T * pThis, void (T::*pFunc)())
{
return new MemberFuncEventHandler<T>(pThis, pFunc);
}
您也可以类似地定义一个处理程序类的静态方法。然后,你可以做这样的事情:
Handlers += Handler(obj, &(c1::foo));
Handlers += Handler(obj, &(c2::bar));
Handlers += Handler(blaa); // for static methods...
您可以重载加法运算符,我想。
如果你想使一个回调系统或某事我会建议Boost.Signals库。基本上,它聚集功能,并调用命令相应的功能基团(如任何其它信号的库),但它也被设计以Boost.Bind和来自Boost.Function其是真棒。
的工作示例:
using boost::function
using boost::bind
using boost::signal
void some_other_func();
Foo a;
Bar b;
signal<void()> sig;
sig.connect(bind(&Foo::foo,&a));
sig.connect(bind(&Bar::bar,&b));
sig.connect(some_other_func);
sig(); // calls -> a.foo(), b.bar(), some_other_func()
还支持阻挡,复杂的连接管理和其它东西整齐