C++ C++;对非静态接口方法的回调
我有一个类a,它应该从接口类B调用一个非静态类方法,签名由以下函数指针表示:C++ C++;对非静态接口方法的回调,c++,function-pointers,C++,Function Pointers,我有一个类a,它应该从接口类B调用一个非静态类方法,签名由以下函数指针表示: bool(B::*检查)(int)const 这种方法将由一组实现B的类{C}实现,每个类都有多个与上述签名匹配的方法。因此,我需要将回调从A绑定到B,这反过来又将委托给从C选择的方法 用一些代码编辑: 这是我心中想法的草图。请注意,这只是上述要求的一个示例,代码组织中的任何内容在A类之外都不是强制性的 class B { public: bool check(int val) const {
bool(B::*检查)(int)const
这种方法将由一组实现B的类{C}实现,每个类都有多个与上述签名匹配的方法。因此,我需要将回调从A绑定到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类
让我感到困惑的是,我还没有找到一个解决方案来满足这个非常特殊的需求。听起来你想使用观察者模式来允许a持有bool(B:*check)(int)const类型的函数指针向量
{C}中的类可以通过observer模式注册到A。如果使用这种模式,我不明白为什么需要显式地使用接口B。接口将由需要所选函数指针签名的函数指针向量保证。听起来您想使用观察者模式来允许A持有布尔(B::*检查)(int)常量类型的函数指针向量
{C}中的类可以通过observer模式注册到A。如果使用这种模式,我不明白为什么需要显式地使用接口B。接口将由函数指针向量保证,函数指针向量需要您选择的函数指针的签名。Massive Edit 我想我得到了你想要的,基于一些重型铸造 请注意,我不推荐这种技术。虽然我的例子很有效,但我相信这里有一些很大的陷阱,可能会把事情搞砸 与前面一样,类
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;
}
大规模编辑 我想我得到了你想要的,基于一些重型铸造 请注意,我不推荐这种技术。虽然我的例子很有效,但我相信这里有一些很大的陷阱,可能会把事情搞砸 与前面一样,类
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;
}
您可以做的最简单的事情不是使用成员函数指针,而是使用更高阶的构造,如
function
(或者boost
或者C++11),并使用bind
(同样,boost
或者C++11)注册回调,而是像function
(或者boost
或者C++11)这样的高阶构造,并用bind
注册回调(同样,boost
或者C++11)。指向成员函数的指针可用,并且完全按照您的意愿执行。但是,请注意,它们实际上不是“指针”,而是“类似指针的”,因为正确的查找/调用可能必须通过与可能有多个父类的类关联的“vptr”表
简言之:是的,你可以拥有它。如果在模板中实现,则不需要包含目标标头(但需要在代码扩展点实现目标类标头)。如果实现为非模板,则可以向前声明成员函数并使其工作。或者,您可以简单地包含目标类类型头
由于有多个目标函数可用,是的,在实际绑定时,必须包含标头(如果这是模板实现,则不需要标头):
[UPDATE],基于更新的代码,您似乎只想在基类中将“bool B::check(int)const
”设置为“虚拟”,并在派生的“C1
”和“C2
”类中重写/重新实现该函数
是的,将调用virtual
函数(在C1
和C2
类中的实现),即使您的指针最初指向B::check(int)
函数。这就是为什么指向成员函数的指针不完全是指针,而是类似指针的(允许调用在派生类中正确执行virtual
代码)
所以,不用担心:它会起作用的,只需将“virtual
”放在B::check(int)
的底部即可。指向成员函数的指针可用,并完全按照您的要求执行。但是,请注意,它们实际上不是“指针”,而是“点”