我有一个A类应该从接口类B调用非静态类方法,其签名由以下函数指针表示:
bool (B::*check)(int) const
这种方法将由一组实现B的类{C}实现,每个类具有与上述签名匹配的多个方法。因此,我需要将回调从A绑定到B,然后B将委托给C中选择的方法。
使用某些代码编辑:
这是我的想法草图。请注意,这只是上述要求的一个示例,代码组织中的任何内容都不是强制性的,可能是A类。
class B {
public:
bool check(int val) const {
// call to a binded method with a given signature (sig) on a Cx class
...
}
};
class C1: public B {
...
// a method implementing the (sig) signature
// another method implementing the (sig) signature
};
class C2: public B {
...
// a method implementing the (sig) signature
// another method implementing the (sig) signature
};
class A {
public:
...
private:
bool result;
int val;
void call_check(B const& b) const {
result = b.check(val);
}
...
};
这可能在C ++中?或者等价地,什么是允许A只知道B类的解决方案?
令我困惑的是,我还没有找到解决这个特殊需求的解决方案。
答案 0 :(得分:1)
大量修改
我认为我得到了你想要的东西,基于一些沉重的类型铸造。
请注意,我 NOT 推荐此技巧。虽然我的例子有效,但我相信这里有一些很大的陷阱可能会让事情搞砸。
与以前一样,类A
可以同时接受正确签名的方法和类型为B
的对象,或者来自类型B
的对象,例如C
}),并在指定的对象上调用指定的方法。
类B
实际上根本没有任何方法,只能作为两个类C1
&的公共基类。 C2
。
底部是main
,演示了如何使用它。我遗漏了两个SetCallback***
方法的实现,因为它们很简单。
class B
{ public: // Has nothing, only serves as base-class for C1 and C2.
};
class C1: public B
{
public: bool DoThis(int x) const { return true; }
};
class C2: public B
{
public: bool DoThat(int x) const { return false; }
};
class A
{
private:
bool (B::*m_check)(int) const;
B* m_Obj;
public:
void SetCallbackFunction(bool (B::*fnc)(int) const)
{ m_check = fnc; }
void SetCallbackObject(B* pB)
{ m_Obj = pB; }
bool InvokeCallback(int val)
{
return (m_Obj->*m_check)(val);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
C1 c;
bool (C1::*func)(int) const;
bool (B::*b_func)(int) const;
func = &C1::DoThis;
b_func = (bool (B::*)(int) const)(func); // Dangerous Typecasting. Use caution!
a.SetCallbackFunction(b_func);
a.SetCallbackObject((B*)(&c)); // A simpler, safer typecast.
a.InvokeCallback(5); // Ends up calling C1::DoThis.
_getch();
return 0;
}
答案 1 :(得分:1)
您可以做的最简单的事情是不使用成员函数指针,而是使用更高阶的构造,如function
(boost
或C ++ 11),并使用{{注册回调1}}(再次,bind
或C ++ 11)。
答案 2 :(得分:1)
指针到成员功能可用,并且可以完全按照您的要求进行操作。但是,请注意它们实际上并不是“指针”,而是“指针式”,因为可能正确的查找/调用必须通过“vptr”表关联与一个可能有多于一个父母的类。
简而言之:是的,你可以拥有它。如果在模板中实现,则不需要包含目标标头(但 需要在代码扩展时实现目标类标头)。如果您实现为非模板,那么可以转发声明成员函数并使其工作。或者,您可以简单地包含目标类类型标题。
由于有多个目标函数可用,是的,在实际绑定时,必须包含标题(如果这是模板实现,则不需要标题):
class MyA {
public:
bool foo1(int) const;
bool foo2(int) const;
};
void MyFunc(void) {
bool (MyA::*my_ptr_to_func)(int) const;
my_ptr_to_func = &MyA::foo2;
MyA my_a;
// call it
if((my_a.*my_ptr_to_func)(42))
{
// ...
}
}
[更新] ,根据您更新的代码,您似乎只想让“bool B::check(int) const
”成为基类中的“virtual
”,并且在派生的“C1
”和“C2
”类中覆盖/重新实现该函数?
是的,virtual
函数将被调用(C1
和C2
类中的实现),即使您的指针最初是B::check(int)
函数。这是有效的,并且正是为什么指向成员函数的指针不是完全指针,而是指针式(允许)您调用以在派生类中正确执行virtual
代码。)
所以,不要害怕:它会起作用,只需将“virtual
”放在B::check(int)
的基础上。
答案 3 :(得分:0)
听起来你想使用观察者模式允许A持有bool (B::*check)(int) const
类型的函数指针向量。
{C}中的类可以通过观察者模式注册到A.我不明白为什么你需要一个接口B,如果你使用这种形式的模式。接口将由需要签名所选函数指针的函数指针向量保证。