C++ 运算符优先级与函数指针

C++ Operator Precedence with function pointer

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 和..下一个?我无法遵循代码。

(我想要像 这样的描述)

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

很清楚,比link的问题还清楚。一一访问iter中的成员。

如果您对 handle->*(iter) 感到困惑... ->->* 几乎相同,只是 -> 接受成员名称而 ->* 接受成员名称指针。

如果你和括号混淆了,因为运算符->*的优先级大于->*.

我从 cppreference.com 回忆起 C++ Operator Precedence:

  • operator-> 具有优先级 2(更高)
  • operator->* 具有优先级 4(较低)。

两者都是从左到右(尽管恕我直言,这在这里不起作用)。

也就是说,在

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

operator->先解决,operator->*后解决。

即上面的表达式等同于

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

请注意,标识符 iter 有点误导。 iter 不是迭代器(并且 iterator 对于容器和数组具有截然不同的含义)。 相反,for (auto& 中的 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;
}

尽管如此,我仍然没有完全理解它(我太不耐烦了 fiddle 这个)——编译器似乎是这样。它毫无怨言地编译:

Live Demo on coliru

事情是这样的(我把它简化成一个可行的例子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);
        }
    }
}

根据 operator precedence 成员访问的规则 -> 优先于指向成员的指针 *-> 因此顺序如下:

  • 一个。 iter->handle 获取句柄指针 EventListener*
  • 乙。 iter->functionClass获取成员函数指针 ftOnEventClass
  • 摄氏度。 (A*->B)(123) 用参数调用成员函数

由于运算符->的优先级高于->*(见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 可能指向什么。