【问题标题】:C++ function pointer (class member) to non-static member function指向非静态成员函数的 C++ 函数指针(类成员)
【发布时间】:2010-11-02 16:49:55
【问题描述】:
class Foo {
public:
    Foo() { do_something = &Foo::func_x; }

    int (Foo::*do_something)(int);   // function pointer to class member function

    void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }

private:
    int func_x(int m) { return m *= 5; }
    int func_y(int n) { return n *= 6; }
};

int
main()
{
    Foo f;
    f.setFunc(false);
    return (f.*do_something)(5);  // <- Not ok. Compile error.
}

我怎样才能让它工作?

【问题讨论】:

  • func_xfunc_y 不是静态函数,即使它们没有被标记为静态函数?

标签: c++ function-pointers


【解决方案1】:

试试 (f.*do_something)(5);

【讨论】:

    【解决方案2】:
     class A{
        public:
            typedef int (A::*method)();
    
            method p;
            A(){
                p = &A::foo;
                (this->*p)(); // <- trick 1, inner call
            }
    
            int foo(){
                printf("foo\n");
                return 0;
            }
        };
    
        void main()
        {
            A a;
            (a.*a.p)(); // <- trick 2, outer call
        }
    

    【讨论】:

    • Tudok,第二次浏览您的帖子后,我意识到您也给出了正确的答案(技巧2)。谢谢。
    • 您的代码不起作用。我复制/粘贴并尝试编译。 test_function_pointer_2.C:在构造函数“A::A()”中:test_function_pointer_2.C:7:错误:“int (A::)()”类型的参数与“int (A::*)()”不匹配
    • @user180574,我记得它确实有效。无论如何,你是对的。我用 gcc 测试了它并得到了同样的错误。我修好了。
    【解决方案3】:

    你想要的线是

       return (f.*f.do_something)(5);
    

    (可以编译——我试过了)

    *f.do_something”指的是指针本身——“f”告诉我们从哪里获取do_something值。但是当我们调用函数时,我们仍然需要提供一个对象作为 this 指针。这就是我们需要“f.”前缀的原因。

    【讨论】:

    • 从技术上讲,“f.do_something”返回指针,“.*”运算符调用类的指向成员函数。
    • 所以我认为return (f.*Foo::do_something)(5) 也应该可以工作。
    • @ThomasMcLeod 它没有。
    • 啊,但这意味着如果你有Foo g,那么这也将编译并运行:return (g.*f.do_something)(5); 对吗? (即使没有充分的理由这样做)
    • @ThomasMcLeod 不,因为Foo::do_something 命名了类的数据成员。您需要一个实例来访问非静态数据成员。
    【解决方案4】:

    我认为调用类的非静态成员也可以使用静态成员函数来完成。

    【讨论】:

    • 这是不可能的。 "在类声明中修改数据成员时,static 关键字指定该成员的一份副本由该类的所有实例共享。当在类声明中修改成员函数时,static 关键字指定该函数只访问静态成员。"见MSDN reference
    • 好吧,您可以通过构造函数保留所有实例的列表,然后为所有实例调用它,但我想这有点糟糕:p
    【解决方案5】:
    class A {
        int var;
        int var2;
    public:
        void setVar(int v);
        int getVar();
        void setVar2(int v);
        int getVar2();
        typedef int (A::*_fVar)();
        _fVar fvar;
        void setFvar(_fVar afvar) { fvar = afvar; }
        void insideCall() { (this->*fvar)(); }
    };
    
    void A::setVar(int v)
    {
        var = v;
    }
    
    int A::getVar()
    {
        std::cout << "A::getVar() is called. var = " << var << std::endl;
        return var;
    }
    
    void A::setVar2(int v2)
    {
        var2 = v2;
    }
    
    int A::getVar2()
    {
        std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
        return var2;
    }
    
    int main()
    {
        A a;
        a.setVar(3);
        a.setVar2(5);
    
    //    a.fvar = &A::getVar;
        a.setFvar(&A::getVar);
        (a.*a.fvar)();
    
        a.setFvar(&A::getVar2);
        (a.*a.fvar)();
    
        a.setFvar(&A::getVar);
        a.insideCall();
    
        a.setFvar(&A::getVar2);
        a.insideCall();
    
        return 0;
    }
    

    我扩展了 Nick Dandoulakis 的回答。谢谢你。

    我添加了一个从类外部设置成员函数指针的函数。我添加了另一个可以从外部调用的函数来显示成员函数指针的内部调用。

    【讨论】:

    • 不要只发布一段代码,请解释为什么这段代码可以解决所提出的问题。没有解释,这不是答案。
    • @MartijnPieters 我写道,它是从 Nick Dandoulakis 的回答中扩展而来的。里面有解释。我是 stackoverflow 的新手,也许我需要以不同的方式做。
    • 嗯,你可以解释一下你做了什么改变,例如,为什么。
    【解决方案6】:
    #include<iostream>
    using namespace std;
    
    class A {
    
    public:
        void hello()
        {
            cout << "hello" << endl;
        };
    
        int x = 0;
    
    };
    
    
    void main(void)
    {
    
        //pointer
        A * a = new A;
        void(A::*pfun)() = &A::hello;
        int  A::*v1 = &A::x;
    
        (a->*pfun)();
        a->*v1 = 100;
        cout << a->*v1 << endl << endl;
    
        //----------------------------- 
        A  b;
        void(A::*fun)() = &A::hello;
        int  A::*v2 = &A::x;
    
        (b.*fun)();
        b.*v2 = 200;
        cout << b.*v2 << endl;
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      相关资源
      最近更新 更多