【问题标题】:Passing pointers to member function as returned values to QObject::connect()将指向成员函数的指针作为返回值传递给 QObject::connect()
【发布时间】:2019-04-22 16:33:32
【问题描述】:

出于设计原因,我需要想出一种调用QObject::connect() 的方法,其中函数指针作为函数调用的返回值传入。也就是说,我必须执行以下操作,而不是使用 vanilla 语法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() );

我在这里做错了什么?

【问题讨论】:

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


【解决方案1】:

您的函数没有返回成员函数指针。 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。并且实现需要限定要返回的成员的名称,并使用地址运算符&amp;

必须对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】:

    您的 get_funcs 没有返回指向成员函数的指针,这正是 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;
    }
    

    【讨论】:

      【解决方案3】:

      一种可能的解决方案是使用auto 推断类型(C++14)并返回&amp;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;
          }
      };
      

      【讨论】:

        【解决方案4】:

        您可以使用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 很容易将其作为结果类型。

        【讨论】:

          猜你喜欢
          • 2018-11-21
          • 2018-12-07
          • 1970-01-01
          • 2013-08-11
          • 2012-07-22
          • 2020-06-09
          • 2012-08-01
          • 2017-01-19
          • 2017-05-16
          相关资源
          最近更新 更多