将指向成员函数的指针作为返回值传递给QObject :: connect()

时间:2018-11-20 09:03:17

标签: c++ qt c++11 qt5 c++14

出于设计原因,我需要想出一种方法来调用QObject::connect(),其中函数指针作为函数调用的返回值传递。即,我不必使用原始语法connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue);,而必须执行以下操作:

//in main.cpp
SENDER *sender = new SENDER;
RECEIVER *receiver = new RECEIVER;
connect(sender, sender->get_func(), receiver, receiver->get_func() );

其中SENDER和RECEIVER的定义如下:

#include <QObject>

class SENDER : public QObject {

  Q_OBJECT
  public:
    void(* get_func() ) (double, double);

  signals:
    void send_data(double x, double y);

};


void (* SENDER::get_func() )(double, double)
{
    return send_data;
}


class RECEIVER : public QObject {

  Q_OBJECT
  public:
    void receive_data(double x, double y);
    void(* get_func() ) (double, double);

};

void (* RECEIVER::get_func() )(double, double)
{
    return receive_data;
}


int main()
{
    SENDER *sender = new SENDER;
    RECEIVER *receiver = new RECEIVER;
    QObject::connect(sender, sender->get_func(), receiver, receiver->get_func() );
}

尝试编译会给我以下错误:

/home/abc/work/mainwindow.cpp:41: error: no matching function for call to ‘MainWindow::connect(SENDER*&, void (*)(double, double), RECEIVER*&, void (*)(double, double))’
     connect(sender, sender->get_func(), receiver, receiver->get_func() );

我在这里做什么错了?

4 个答案:

答案 0 :(得分:2)

您的get_func不会返回指针指向成员的函数,这是connect期望的。他们正在返回指向功能的指针。

当您返回成员函数(语法错误)时,它们的 body 也将无法编译。

您应该改为将其声明为

//sender.h
#include <QWidget>

class SENDER : public QWidget{

  Q_OBJECT
  public:
    void (SENDER::*get_func)(double, double)();

  signals:
    void send_data(double x, double y);

};

//sig_sender.cpp
#include "sender.h"

void (SENDER::*)(double, double) SENDER::get_func()
{
    return &SENDER::send_data;
}

//sig_receiver.h
#include <QWidget>

class RECEIVER : public QWidget{

  Q_OBJECT
  public:
    void receive_data(double x, double y);
    void (RECEIVER::*get_func)(double, double)();

};

//sig_receiver.cpp
#include "receiver.h"

void (RECEIVER::*)(double, double) RECEIVER::get_func()
{
    return &RECEIVER::receive_data;
}

答案 1 :(得分:2)

您的函数未返回成员函数指针。 SENDER的写法如下:

class SENDER : public QObject {

  Q_OBJECT
  public:
    void (SENDER::*get_func())(double, double);

  signals:
    void send_data(double x, double y);

};


void (SENDER::*SENDER::get_func())(double, double)
{
    return &SENDER::send_data;
}

get_func()需要声明为返回指向成员函数的指针,该指针采用(double, double)并返回void。实现需要限定要返回的成员的名称,并使用地址操作符&

必须对RECEIVER进行类似的更改:

class RECEIVER : public QObject {

  Q_OBJECT
  public:
    void receive_data(double x, double y);
    void (RECEIVER::*get_func())(double, double);
};

void (RECEIVER::*RECEIVER::get_func())(double, double)
{
    return &RECEIVER::receive_data;
}

答案 2 :(得分:1)

一种可能的解决方案是使用auto推导类型(C ++ 14)并返回&Class::method

#include <QCoreApplication>
#include <QTimer>
#include <QDebug>

class SENDER : public QObject{
    Q_OBJECT
public:
    auto get_func(){
        return &SENDER::send_data;
    }
signals:
    void send_data(double x, double y);
};

class RECEIVER : public QObject
{
    Q_OBJECT
public:
    void receive_data(double x, double y){
        qDebug()<< __PRETTY_FUNCTION__ << x <<y;
        QCoreApplication::quit();
    }
    auto get_func(){
        return &RECEIVER::receive_data;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SENDER *sender = new SENDER;
    RECEIVER *receiver = new RECEIVER;
    QObject::connect(sender, sender->get_func(), receiver, receiver->get_func());
    QTimer::singleShot(1000, sender, [sender](){
        emit sender->send_data(1.0, 2.0);
    });
    return a.exec();
}

#include "main.moc"

或者:

class SENDER : public QObject{
    Q_OBJECT
public:
    void (SENDER::*get_func())(double, double){
        return &SENDER::send_data;
    }
signals:
    void send_data(double x, double y);
};

class RECEIVER : public QObject
{
    Q_OBJECT
public:
    void receive_data(double x, double y){
        qDebug()<< __PRETTY_FUNCTION__ << x <<y;
        QCoreApplication::quit();
    }
    void (RECEIVER::*get_func())(double, double){
        return &RECEIVER::receive_data;
    }
};

答案 3 :(得分:1)

您可以使用usingtypedef来定义指向成员函数的指针的类型:

class SENDER : public QWidget{
  Q_OBJECT
  public:
    typedef void (SENDER::*PtrFunc)(double,double); // PtrFunc pointer to member function
    PtrFunc get_func () { return &SENDER::send_data; }
  signals:
    void send_data(double x, double y) {}
};


class RECEIVER : public QWidget{
  Q_OBJECT
  public:
    using PtrFunc = void (RECEIVER::*)(double,double);
    void receive_data(double x, double y) {}
    PtrFunc get_func() { return &RECEIVER::receive_data; }
};

SENDER* sender;
RECEIVER* receiver;
//..
QObject::connect (sender, sender->get_func(), receiver, receiver->get_func());

使用typedef可以很容易地将其作为结果类型。