Как вызвать функцию-член через указатель на нее, которая является членом данных? - PullRequest
1 голос
/ 15 марта 2020

У меня есть некоторая путаница относительно того, как использовать указатель на функцию-член, которая сама является членом-данными:

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.pMemFunc или pF->pMemFunc, а затем разыменовывать его, чтобы получить функцию-член, которой нужен объект для вызова, поэтому я пытаюсь: f.(*f.pMemFunc)(10);, но я получаю ошибку во время компиляции .

Пожалуйста, объясните, как это сделать. Спасибо!

  • Я наконец-то каким-то образом заработал после многих попыток: разбить выражение на части:

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

Но объясните пожалуйста, почему сейчас это работает и что происходит?

Ответы [ 2 ]

0 голосов
/ 15 марта 2020

Наконец мне удалось заставить его работать, взглянув на предыдущий обходной путь, заменив ret на соответствующее подвыражение:

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

Но это выглядит уродливо, если дважды ввести f. Любые предложения или советы высоко ценятся.

0 голосов
/ 15 марта 2020

Я предлагаю вам использовать std::function для хранения указателя функции в качестве члена.

Для функции-члена объект является неявным первым аргументом функции. Вы можете использовать std::bind, чтобы связать функцию с указанным c объектом (через первый аргумент). Преимущество состоит в том, что вы можете отделить привязку к объекту от вызова функции (скажем, на этапе подготовки).

С 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);

Вместо непосредственного использования &Foo::function указатель функции или std::function может быть задан в качестве первого аргумента bind().

...