如何声明一个带有指向成员函数的函数

Posted

技术标签:

【中文标题】如何声明一个带有指向成员函数的函数【英文标题】:How to declare a function that takes a pointer-to-member function 【发布时间】:2018-01-25 12:26:53 【问题描述】:

我有一个类,其成员变量指向库对象。

class myClassA 
private:
    libraryClass *libraryObject;

库类发出事件,以字符串为特征,并提供一种机制,允许客户端类指定在事件发出时应调用的成员函数,所以在myClassA中,我可以的

libraryObject->connect ("eventName", this, &myClassA::privateMember);

我现在希望 myClassA 的客户能够通过将公共成员函数 connect 添加到 myClassA。我应该如何在myClassA头文件中声明connect

具体来说,我正在使用 Qt 并尝试允许客户端(myClassA)调用 QScxmlStateMachine::connectToEvent。此函数的Qt documentation 将其描述为

QMetaObject::Connection QScxmlStateMachine::connectToEvent(
            const QString &scxmlEventSpec,
            const QObject *receiver,
            PointerToMemberFunction method,
            Qt::ConnectionType type = Qt::AutoConnection)

但我不清楚应该如何定义 PointerToMemberFunction

Qt头文件声明为

template <typename Func1>
QMetaObject::Connection connectToEvent(
        const QString &scxmlEventSpec,
        const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot,
        Qt::ConnectionType type = Qt::AutoConnection);

与其只是盲目地将它复制到我的代码中并查看它是否有效,请有人向我解释这个声明;特别是我读到它说某些东西是模板化的,我不明白什么,以及为什么我不需要做任何模板-y 来使用该机制。

谢谢。

【问题讨论】:

使用模板,就像所有standard C++ algorithm functions 使用谓词一样?还是std::function?这些中的任何一个都将使您的生活更轻松。 :) 如果您需要调用 QScxmlStateMachine::connectToEvent 函数,那么您应该使用相同类型的参数。只需使用 PointerToMemberFunction 作为类型。 connectToEvent 期望接收此类型的第三个参数。 【参考方案1】:

在提出问题的同时浏览所有各种包含文件使我能够解决此问题。

我在 myClassA

的头文件中包含以下内容
template <typename Func1>           // Lifted from QtScxmlStateMachine.h
QMetaObject::Connection connectToEvent(
        const QString &scxmlEventSpec,
        const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot,
        Qt::ConnectionType type = Qt::AutoConnection) 
    return libraryObject->connectToEvent(scxmlEventSpec, receiver, slot, type);
;

myClassA 的客户端现在可以调用 myClassA::connectToEvent 来调用底层 QtScxmlStateMachineconnectToEvent 成员.

谢谢你,***,是你强迫我正确地整理自己的想法。

【讨论】:

【参考方案2】:

QtPrivate::FunctionPointer 是一个类型特征模板,有助于新的 Qt 信号/槽语法。

How Qt Signals and Slots Work - Part 2 - Qt5 New Syntax

类型特征:QtPrivate::FunctionPointer

特征基本上是一个帮助类,它提供有关给定的元数据 类型。 Qt 中 trait 的另一个例子是QTypeInfo

为了实现新语法,我们需要知道的是 关于函数指针的信息。

template&lt;typename T&gt; struct FunctionPointer 会给我们 有关T 的信息,请通过其成员。

ArgumentCount:一个整数,表示函数的参数个数。

Object:仅针对指向成员函数的指针存在。它是函数所属类的 typedef。

Arguments:表示参数列表。它是元编程列表的 typedef。

call(T &amp;function, QObject *receiver, void **args):一个静态函数,将调用该函数,应用给定的参数。

...

FunctionPointer的实现在于qobjectdefs_impl.h。

此 trait 允许根据提供的参数选择正确的 QScxmlStateMachine::connectToEvent - QObject 槽、函子或函数指针(无论有无上下文)。

// connect state to a QObject slot
template <typename Func1>
inline QMetaObject::Connection connectToEvent(
        const QString &scxmlEventSpec,
        const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot,
        Qt::ConnectionType type = Qt::AutoConnection)


// connect state to a functor or function pointer (without context)
template <typename Func1>
inline typename QtPrivate::QEnableIf<
        !QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
        !std::is_same<const char*, Func1>::value, QMetaObject::Connection>::Type
connectToEvent(const QString &scxmlEventSpec, Func1 slot,
               Qt::ConnectionType type = Qt::AutoConnection)

// connectToEvent to a functor or function pointer (with context)
template <typename Func1>
inline typename QtPrivate::QEnableIf<
        !QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
        !std::is_same<const char*, Func1>::value, QMetaObject::Connection>::Type
connectToEvent(const QString &scxmlEventSpec, QObject *context, Func1 slot, Qt::ConnectionType type = Qt::AutoConnection)

因此,如果您需要允许所有情况,您可以提供具有相同原型的方法并转发参数。

【讨论】:

以上是关于如何声明一个带有指向成员函数的函数的主要内容,如果未能解决你的问题,请参考以下文章

在类声明中处理指向成员函数的指针

指向具有私有构造函数的类的类成员的指针

如何在 C++ 中指向全局函数中的成员函数?

指向带有 boost::variant 的成员函数的指针

如何使用指向类的成员函数的指针(详解!)

如何从静态成员函数调用指向成员函数的指针?