Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;对非静态接口方法的回调_C++_Function Pointers - Fatal编程技术网

C++ C++;对非静态接口方法的回调

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 {

我有一个类a,它应该从接口类B调用一个非静态类方法,签名由以下函数指针表示:

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)
的底部即可。

指向成员函数的指针可用,并完全按照您的要求执行。但是,请注意,它们实际上不是“指针”,而是“点”