Приоритет оператора C ++ с указателем на функцию - PullRequest
0 голосов
/ 05 октября 2018
class EventListener
{
public:
  const char* getName() { return name; }
  EventListener();
  EventListener(const string& n);

  void addTime(CrChkTime t) { time += t; }
  void resetTime() { time = 0; }
  CrChkTime getTime() { return time; }

private:
  virtual void dummy() {}

  const char* name;
  CrChkTime time;
};

typedef void (EventListener::*ftOnEventClass)(int kind, int param1, void* param2, bool& ret);

typedef struct _eventNode
  {
    /** For c handlers */
    ftOnEvent function;
    /** For c++ handlers */
    ftOnEventClass functionClass;
    /** Handle */
    EventListener* handle;

    /*...constructors...*/
} EventNode;

vector<vector<EventNode *>> m_vEventHandlerList;
for(auto& iter : m_vEventHandlerList[kind])
{
    if(iter->handle != nullptr)
    {
         (iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);
    }
}

,

(iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);

- это вызов функции и рабочий код.(и это может быть указатель на функцию)

пожалуйста, не могли бы вы описать меня с приоритетом оператора следующего выражения?

(iter->handle->*(iter)->functionClass)

iter-> handle и .. next?я не могу следовать за кодом.

(я хочу описание как https://stackoverflow.com/a/27283893/3818785 this)

Ответы [ 4 ]

0 голосов
/ 05 октября 2018

Поскольку оператор -> имеет более высокий приоритет, чем ->* (см. https://en.cppreference.com/w/cpp/language/operator_precedence),, выполняется следующий анализ:

(iter->handle->*(iter)->functionClass)

эквивалентен:

( (iter->handle) ->* (iter->functionClass) )

iter->handle имеет тип EventListener*

iter->functionClass имеет тип ftOnEventClass

Таким образом, все выражение является разыменованием функции указателя на член с использованием объекта, на который указывает iter->handle.

Дело в том, что я не вижу функции-члена в EventListener, которая имеет список аргументов:

(int, int, void*, bool&)

Так что я не вижу, что могло iter->functionClassуказывать на.

0 голосов
/ 05 октября 2018

Я вспомнил Приоритет оператора C ++ с cppreference.com:

  • operator-> имеет приоритет 2 (выше)
  • operator->* имеет приоритет 4 (ниже).

и оба слева направо (хотя, ИМХО, здесь это не играет роли).

Это значит,в

(iter->handle->*(iter)->functionClass)

operator-> решается первым, operator->* впоследствии.

Т.е. указанное выше выражение эквивалентно

((iter->handle)->*((iter)->functionClass))

Обратите внимание, что идентификатор iter немного вводит в заблуждение.iter не является итератором (а iterator имеет совершенно другое значение для контейнеров и массивов).Вместо этого auto& в for (auto& ... предоставляет ссылку на текущий элемент (для каждого элемента в контейнере после :).(Может быть, я немного ломаю голову - извините.)

Меня немного беспокоило двойное вхождение iter в выражении в квесте.Поэтому я попытался завершить пример кода OP, чтобы сделать его MCVE :

// The following things have been added to make this an MVCE

#include <string>
#include <vector>

using namespace std;

struct CrChkTime {
  CrChkTime(int) { }
  CrChkTime& operator=(int) { return *this; }
  CrChkTime& operator+=(const CrChkTime&) { return *this; }
};

// sample code of OP:

class EventListener
{
public:
  const char* getName() { return name; }
  EventListener();
  EventListener(const string& n);

  void addTime(CrChkTime t) { time += t; }
  void resetTime() { time = 0; }
  CrChkTime getTime() { return time; }

private:
  virtual void dummy() {}

  const char* name;
  CrChkTime time;
};

typedef void (EventListener::*ftOnEventClass)(int kind, int param1, void* param2, bool& ret);

typedef struct _eventNode
  {
    /** For c handlers */
    // Excluded: ftOnEvent function;
    /** For c++ handlers */
    ftOnEventClass functionClass;
    /** Handle */
    EventListener* handle;

    /*...constructors...*/
} EventNode;

int main()
{
    vector<vector<EventNode *>> m_vEventHandlerList;

    int kind = 0, param1 = 0; void *param2 = nullptr; bool ret; // Missing.

    for(auto& iter : m_vEventHandlerList[kind])
    {
        if(iter->handle != nullptr)
        {
             (iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);
        }
    }
    return 0;
}

Хотя я до сих пор не понимаю его в деталях (я был слишком нетерпелив, чтобыпоиграть) - так выглядит компилятор.Компилируется без жалоб:

Live демо на coliru

0 голосов
/ 05 октября 2018

Вот что происходит (я упростил это до работоспособного примера https://ideone.com/g8IL8s)

#include <iostream>
#include <vector>


class EventListener
{
public:
    void test(int n)
    {
        std::cout << "n is: " << n << std::endl;
    }
};

typedef void (EventListener::*ftOnEventClass)(int n);

struct EventNode
{
    ftOnEventClass functionClass;
    EventListener* handle;
};


int main()
{
    std::vector<EventNode *> m_vEventHandlerList;
    EventListener el;
    EventNode en = { &EventListener::test, &el};
    m_vEventHandlerList.push_back(&en);

    for (auto& iter : m_vEventHandlerList)
    {
        if (iter->handle != nullptr)
        {
            (iter->handle->*iter->functionClass)(123);
        }
    }
}

Согласно правилам приоритет оператора доступ к элементу -> имеет приоритет над указателем наmember *-> Итак, вот порядок:

  • A. iter->handle получает указатель дескриптора EventListener*
  • B. iter->functionClass получает указатель на функцию-член ftOnEventClass
  • C. (A*->B)(123) вызывает функцию-член с аргументом
0 голосов
/ 05 октября 2018
iter
->
handle
->*
(iter)
->
functionClass

ооочень ясно, более понятно, чем вопрос ссылки.Доступ к членам из iter один за другим.

Если вас смущают, что handle->*(iter) ... -> и ->* почти одинаковы, за исключением того, что -> принимает имя члена и ->* принимаетуказатель.

Если вы перепутали с круглыми скобками, потому что приоритет операторов -> и * больше ->*.

...