Передача указателей на функцию-член в качестве возвращаемых значений в QObject :: connect () - PullRequest
0 голосов
/ 20 ноября 2018

По соображениям проектирования мне нужно придумать способ вызова 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 голосов
/ 20 ноября 2018

Ваши функции не возвращают указатели на функции-члены.Вот как нужно написать 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.А для реализации необходимо указать имя возвращаемого члена и использовать оператор address-of, &.

Аналогичные изменения необходимо внести в 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;
}
0 голосов
/ 20 ноября 2018

Ваши get_func не возвращают функции указателя на член, что ожидает соединение.Они возвращают указатель на функции.

Их тела также не смогут скомпилироваться, так как вы возвращаете функцию-член (с неверным синтаксисом).

Вместо этого вы должны объявить их как

//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;
}
0 голосов
/ 20 ноября 2018

Вы можете использовать using или typedef, чтобы определить тип для указателя на функцию-член:

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 его легко поместить в качестве типа результата.

0 голосов
/ 20 ноября 2018

Одним из возможных решений является использование 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;
    }
};
...