【问题标题】:How to call a member function through a pointer to it that is a member data?如何通过指向成员数据的指针调用成员函数?
【发布时间】:2020-03-15 09:59:54
【问题描述】:

我对如何使用指向成员数据本身的成员函数的指针有些困惑:

struct Foo
{
    void bar(int x)
    {    
      cout << x << endl;
    }
    double getVal(double d)
    {
       return ++d;
    }

    void(Foo::*pMemFunc)(int) = &Foo::bar;// ptr to mem func
    int(Foo::*pMemI) = &Foo::val_;// ptr to mem data
    int* pI = &val_; 
    int val_ = 57;
};


int main()
{

    Foo f, *pF = new Foo{};

    double(Foo::*pMemFun)(double) = 
  &Foo::getVal;

    cout << (f.*pMemFun)(3.14) << endl;// dereferencing a pMemFun yields a the member getVal so we need an object or pointer to call it.  
    cout << (pF->*pMemFun)(2.08) << endl;// through pointer to Foo obj

    f.Foo::pMemFunc = &Foo::bar;
    // f.Foo::pMemFunc(5);// how to use this?


     cout << "\nDone!\n";
}

所以pMemFunc 是一个指向成员函数的指针,但指针本身是类Foo 的成员数据,那么我该如何调用它指向的成员函数呢?

我尝试过这样的事情:

    f.(*f.pMemFunc)(0);

但它不起作用。我发现更难的是访问该成员必须通过一个对象,例如 f.pMemFuncpF-&gt;pMemFunc 然后取消引用它会产生一个需要一个对象来调用它的成员函数,所以我尝试:f.(*f.pMemFunc)(10); 但我得到编译时错误.

请说明如何操作。谢谢!

  • 经过多次尝试,我终于以某种方式让它工作了:将表达式分解为多个部分:

    auto ret = f.pMemFunc; // 1
    (f.*ret)(0);// 2. works fine
    

但是请解释为什么现在它可以工作以及会发生什么?!

【问题讨论】:

  • 第一次和第二次尝试的区别在于你如何设置括号。

标签: c++ pointer-to-member


【解决方案1】:

我建议您使用std::function 将函数指针存储为成员。

对于成员函数,对象是函数的隐式第一个参数。 您可以使用std::bind 将函数绑定到特定对象(通过第一个参数)。优点是您可以将对象的绑定与函数调用分开(例如,在准备步骤中)。

来自https://de.cppreference.com/w/cpp/utility/functional/bind

// bind to a member function
Foo foo;
auto fun = std::bind(&Foo::function, &foo, _1); // _1, _2, .. are placeholders for later arguments
fun(5);

可以将函数指针或std::function 作为bind() 的第一个参数,而不是直接使用&amp;Foo::function

【讨论】:

  • std::bind 不返回 std::function。还应该首选 lambda。
  • 我从来没有说过它返回一个 std::function。请说明您对 lambdas 的偏好。
  • 我建议你使用 std::function 将函数指针存储为成员。 很清楚地暗示这里涉及到std::function 的使用。至于 lambda,应该优先于使用 std::bind。通常它们可以用来达到相同的结果。这里是std::function&lt;...&gt; fun = [&amp;](...){...};
  • 听着。我从来没有说过 std::bind 返回一个 std::function。你的报价也没有说。我问你为什么应该首选 lambda,你只是重申了你的陈述而不是给出理由。虽然我对此没有强烈的看法,但我更喜欢 std::bind() 的原因是它非常明确地说明了它的作用。
  • 我知道你没有这么说。但是我仍然发现您回答中的措辞可能令人困惑,因此我发表了评论。您可以通过 std::bind here 阅读有关 lambda 的更多信息。
【解决方案2】:

最后,我通过查看以前的解决方法,将ret 替换为相应的子表达式,终于让它工作了:

       auto ret = f.pMemFunc;
       (f.*ret)(0);
       (f.*f.pMemFunc)(0);// ok

但是使用f 两次看起来很难看。非常感谢任何建议或提示。

【讨论】:

    猜你喜欢
    • 2015-05-06
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    相关资源
    最近更新 更多