Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Is it possible to have pure virtual slots?
Qt 6.11 is out! See what's new in the release blog

Is it possible to have pure virtual slots?

Scheduled Pinned Locked Moved Solved General and Desktop
39 Posts 6 Posters 7.7k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SPlattenS SPlatten

    @Bonnie, its different, but still not right, now it stops in moc_clsModHelper.cpp on a line which reads:

    case 4: _t->connected(); break;
    

    The Application Output shows:

    libc++abi.dylib: Pure virtual function called!
    
    B Offline
    B Offline
    Bonnie
    wrote on last edited by
    #19

    @SPlatten
    Hmmm...can you post the full header file of clsModFileIO class?

    SPlattenS 1 Reply Last reply
    0
    • J.HilkJ J.Hilk

      @SPlatten sure, but you can always call the base implementation by implicitly invoking it and in many cases you want to do that.

      take for example:

      class BaseClass {
      public:
          virtual void functionA() { qDebug () << "A"; }
      };
      
      class DerivedClass : public BaseClass{
      
      public:
          void functionA() override {qDebug() << "B";}
      
      };
      
      class DerivedClass2: public BaseClass {
      public:
          void functionA() override {
              BaseClass::functionA();
              qDebug() << "B";
          }
      };
      
      int main (int argc, char *argv[])
      {
      
          DerivedClass c1;
          DerivedClass2 c2;
      
          c1.functionA();
          qDebug() << "----";
          c2.functionA();
      
      }
      

      this outputs:

      B
      ----
      A
      B
      

      where the 2nd class implicitly invokes the base implementation.

      SPlattenS Offline
      SPlattenS Offline
      SPlatten
      wrote on last edited by
      #20

      @J-Hilk Its a pure virtual slot for the purpose of defining the structure and interface required to be implemented by the derived classes, thats why they have no implementation.

      Kind Regards,
      Sy

      J.HilkJ 1 Reply Last reply
      0
      • B Bonnie

        @SPlatten
        Hmmm...can you post the full header file of clsModFileIO class?

        SPlattenS Offline
        SPlattenS Offline
        SPlatten
        wrote on last edited by SPlatten
        #21

        @Bonnie , sure:

        These are very much a work in progress:

        clsModHelper.h

            class clsModHelper : public QTcpSocket {
            Q_OBJECT
        
            protected:
                bool mblnExit;
                double mdblVersion;
                FILE* mfpDbgLog;
                qint64 mint64AppPID;
                std::thread* mpHeartbeat;
                std::thread* mpThread;
                static const int mscintConnectionTimeout;
                static const int mscintHeartbeatFrequency;
                static const char* mscpszHost;
                static clsModHelper* mspThis;
                static char msszTitle[MODULE_NAME_LENGTH + 1];
                quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
        
                static bool blnToThisModule(clsJSON& objJSON);
                void cleanup();
                void loopUntilExit();
                void start();
        
            public slots:
                virtual void connected() = 0;
                virtual void dataIn() = 0;
                virtual void disconnected() = 0;
                void errorOccurred(QAbstractSocket::SocketError socketError);
                void exitModule();
                void killThreads();
        
            public:
                static const char mscszAck[]
                               ,mscszCmdHB[]
                             ,mscszCommand[]
                            ,mscszCommands[]
                               ,mscszError[]
                              ,mscszModule[]
                             ,mscszMsgType[]
                                 ,mscszPID[]
                              ,mscszResult[]
                            ,mscszSkipOver[]
                                ,mscszTime[]
                                ,mscszTrue[]
                                ,mscszType[]
                            ,mscszTypeChar[]
                          ,mscszTypeDouble[]
                           ,mscszTypeFloat[]
                             ,mscszTypeInt[]
                            ,mscszTypeLong[]
                           ,mscszTypeShort[]
                          ,mscszTypeString[]
                           ,mscszTypeUChar[]
                            ,mscszTypeUInt[]
                           ,mscszTypeULong[]
                          ,mscszTypeUShort[];      
                explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                     ,const char* cpszTitle, double dblVersion);
                virtual ~clsModHelper();
                double dblGetVersion() { return mdblVersion; }
                [[noreturn]] static void exitMsg(const char* cpszMsg
                                                ,const char* cpszPrefix = "ERROR"
                                                ,int intCode = EXIT_FAILURE);
                qint64 int64GetPID() { return mint64AppPID; }
                int intExitCode() { return 0; }
                static long lngTimeInSecs();
                static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                static const char* cpszGetTitle() { return msszTitle; }
                void queueJSON(QJsonObject& objJSON);
                void sendHeartbeat();
                void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                void threadBody();
                virtual void moduleThreadBody() = 0;
                quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
        
            signals:
                void onFailure(QJsonObject& objCmd);
                void onSuccess(QJsonObject& objCmd);
                void terminateModule();
                void threadTerminated();
            };
        

        clsModFileIO.h:

            class clsModFileIO : public clsModHelper {
            private:
                static clsModFileIO* mspInstance;
        
                void cmdLineSummary();
        
            public:
                static const char mscszCheck[]
                                 ,mscszCmdFind[]
                                 ,mscszCmdRead[]
                                 ,mscszCmdSave[]
                                 ,mscszCmdTell[]
                                 ,mscszCmdWrite[]
                                 ,mscszByteOrder[]
                                 ,mscszData[]
                                 ,mscszFailed[]
                                 ,mscszFile[]
                                 ,mscszFrom[]
                                 ,mscszLength[]
                                 ,mscszMode[]
                                 ,mscszModeBinary[]
                                 ,mscszModeText[]
                                 ,mscszPattern[]
                                 ,mscszPosition[]
                                 ,mscszStart[]
                                 ,mscszSuccess[];
                explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                ~clsModFileIO();
                bool doCommand(QString& strFile, QJsonObject& objRequest
                                               , QJsonObject& objCmd
                                               , QJsonObject& objResponse
                                               , quint16 uint16Idx = 0);        
                void moduleThreadBody() override;
                static clsModFileIO* pInstance() { return mspInstance; }
        
            public slots:
                void connected() override;
                void dataIn() override;
                void disconnected() override;
                void onFailure(QJsonObject& objCmd);
                void onSuccess(QJsonObject& objCmd);
            };
        

        Some additional information:

        Qt Creator 4.13.2
        Based on Qt 5.15.1 (Clang 11.0 (Apple), 64 bit)
        
        Built on Oct 1 2020 01:16:45
        
        From revision 2ee1af2032
        

        Using Qt 5.15.0

        Kind Regards,
        Sy

        B 1 Reply Last reply
        0
        • SPlattenS SPlatten

          @Bonnie , sure:

          These are very much a work in progress:

          clsModHelper.h

              class clsModHelper : public QTcpSocket {
              Q_OBJECT
          
              protected:
                  bool mblnExit;
                  double mdblVersion;
                  FILE* mfpDbgLog;
                  qint64 mint64AppPID;
                  std::thread* mpHeartbeat;
                  std::thread* mpThread;
                  static const int mscintConnectionTimeout;
                  static const int mscintHeartbeatFrequency;
                  static const char* mscpszHost;
                  static clsModHelper* mspThis;
                  static char msszTitle[MODULE_NAME_LENGTH + 1];
                  quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
          
                  static bool blnToThisModule(clsJSON& objJSON);
                  void cleanup();
                  void loopUntilExit();
                  void start();
          
              public slots:
                  virtual void connected() = 0;
                  virtual void dataIn() = 0;
                  virtual void disconnected() = 0;
                  void errorOccurred(QAbstractSocket::SocketError socketError);
                  void exitModule();
                  void killThreads();
          
              public:
                  static const char mscszAck[]
                                 ,mscszCmdHB[]
                               ,mscszCommand[]
                              ,mscszCommands[]
                                 ,mscszError[]
                                ,mscszModule[]
                               ,mscszMsgType[]
                                   ,mscszPID[]
                                ,mscszResult[]
                              ,mscszSkipOver[]
                                  ,mscszTime[]
                                  ,mscszTrue[]
                                  ,mscszType[]
                              ,mscszTypeChar[]
                            ,mscszTypeDouble[]
                             ,mscszTypeFloat[]
                               ,mscszTypeInt[]
                              ,mscszTypeLong[]
                             ,mscszTypeShort[]
                            ,mscszTypeString[]
                             ,mscszTypeUChar[]
                              ,mscszTypeUInt[]
                             ,mscszTypeULong[]
                            ,mscszTypeUShort[];      
                  explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                       ,const char* cpszTitle, double dblVersion);
                  virtual ~clsModHelper();
                  double dblGetVersion() { return mdblVersion; }
                  [[noreturn]] static void exitMsg(const char* cpszMsg
                                                  ,const char* cpszPrefix = "ERROR"
                                                  ,int intCode = EXIT_FAILURE);
                  qint64 int64GetPID() { return mint64AppPID; }
                  int intExitCode() { return 0; }
                  static long lngTimeInSecs();
                  static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                  static const char* cpszGetTitle() { return msszTitle; }
                  void queueJSON(QJsonObject& objJSON);
                  void sendHeartbeat();
                  void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                  void threadBody();
                  virtual void moduleThreadBody() = 0;
                  quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
          
              signals:
                  void onFailure(QJsonObject& objCmd);
                  void onSuccess(QJsonObject& objCmd);
                  void terminateModule();
                  void threadTerminated();
              };
          

          clsModFileIO.h:

              class clsModFileIO : public clsModHelper {
              private:
                  static clsModFileIO* mspInstance;
          
                  void cmdLineSummary();
          
              public:
                  static const char mscszCheck[]
                                   ,mscszCmdFind[]
                                   ,mscszCmdRead[]
                                   ,mscszCmdSave[]
                                   ,mscszCmdTell[]
                                   ,mscszCmdWrite[]
                                   ,mscszByteOrder[]
                                   ,mscszData[]
                                   ,mscszFailed[]
                                   ,mscszFile[]
                                   ,mscszFrom[]
                                   ,mscszLength[]
                                   ,mscszMode[]
                                   ,mscszModeBinary[]
                                   ,mscszModeText[]
                                   ,mscszPattern[]
                                   ,mscszPosition[]
                                   ,mscszStart[]
                                   ,mscszSuccess[];
                  explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                  ~clsModFileIO();
                  bool doCommand(QString& strFile, QJsonObject& objRequest
                                                 , QJsonObject& objCmd
                                                 , QJsonObject& objResponse
                                                 , quint16 uint16Idx = 0);        
                  void moduleThreadBody() override;
                  static clsModFileIO* pInstance() { return mspInstance; }
          
              public slots:
                  void connected() override;
                  void dataIn() override;
                  void disconnected() override;
                  void onFailure(QJsonObject& objCmd);
                  void onSuccess(QJsonObject& objCmd);
              };
          

          Some additional information:

          Qt Creator 4.13.2
          Based on Qt 5.15.1 (Clang 11.0 (Apple), 64 bit)
          
          Built on Oct 1 2020 01:16:45
          
          From revision 2ee1af2032
          

          Using Qt 5.15.0

          B Offline
          B Offline
          Bonnie
          wrote on last edited by Bonnie
          #22

          @SPlatten
          As I remember, the overridden "slots" in the derived class can't be declared as slots.
          So try

             public:
                  void connected() override;
                  void dataIn() override;
                  void disconnected() override;
             public slots:
                  void onFailure(QJsonObject& objCmd);
                  void onSuccess(QJsonObject& objCmd);
          

          BTW, you don't have Q_OBJECT in clsModFileIO class but you can declare slots in it? Is that possible?

          SPlattenS 1 Reply Last reply
          0
          • B Bonnie

            @SPlatten
            As I remember, the overridden "slots" in the derived class can't be declared as slots.
            So try

               public:
                    void connected() override;
                    void dataIn() override;
                    void disconnected() override;
               public slots:
                    void onFailure(QJsonObject& objCmd);
                    void onSuccess(QJsonObject& objCmd);
            

            BTW, you don't have Q_OBJECT in clsModFileIO class but you can declare slots in it? Is that possible?

            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #23

            @Bonnie , I've changed the header to your recommendations, but I'm still ending up with:

            QAbstractSocket::UnconnectedState
            libc++abi.dylib: Pure virtual function called!
            

            Kind Regards,
            Sy

            KroMignonK 1 Reply Last reply
            0
            • SPlattenS SPlatten

              @J-Hilk Its a pure virtual slot for the purpose of defining the structure and interface required to be implemented by the derived classes, thats why they have no implementation.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #24

              @SPlatten maybe we're talking past each other, where are those connects?


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              1 Reply Last reply
              0
              • SPlattenS SPlatten

                @Bonnie , I've changed the header to your recommendations, but I'm still ending up with:

                QAbstractSocket::UnconnectedState
                libc++abi.dylib: Pure virtual function called!
                
                KroMignonK Offline
                KroMignonK Offline
                KroMignon
                wrote on last edited by
                #25

                @SPlatten said in Is it possible to have pure virtual slots?:

                QAbstractSocket::UnconnectedState
                libc++abi.dylib: Pure virtual function called!

                Have you take a look at stackoverflow?

                For my understanding: yes it is possible

                • on base class don't forget to add Q_OBJECT macro
                • on subclass, do not add Q_SLOTS or slots for those slots
                • and finally, don't forget to re-run moc if you change one of those things

                It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                SPlattenS 1 Reply Last reply
                0
                • B Offline
                  B Offline
                  Bonnie
                  wrote on last edited by Bonnie
                  #26

                  As I tested, it doesn't matter where you do the connection, it is also fine to use the new syntax to connect the base class's slot.
                  But it is important that the pure virtual slots cannot be called in the base class's constructor (that's not Qt but c++ basic).
                  Do you call waitForConnected in clsModHelper's constructor?
                  If you do, the solution is to either move waitForConnected out of the constructor (which is the better way), or connect using Qt::QueuedConnection.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #27

                    You're doing something wrong, it works perfectly (and I don't see a reason why it should not - it's plain c++)

                    main.h

                    #pragma once
                    #include <QObject>
                    struct Ifc
                    {
                      virtual void myVirtualSlot() = 0;
                    };
                    class TestClass : public QObject, public Ifc
                    {
                      Q_OBJECT
                    public:
                      TestClass();
                      void myVirtualSlot() override;
                    };
                    

                    main.cpp

                    #include <QtCore>
                    #include "main.h"
                    
                    TestClass::TestClass()
                    {
                      QTimer::singleShot(100, this, &TestClass::myVirtualSlot);
                    }
                    void TestClass::myVirtualSlot()
                    {
                      qDebug() << "Executed!";
                      QCoreApplication::exit(0);
                    }
                    
                    int main(int argc, char** argv)
                    {
                      QCoreApplication app(argc, argv);
                    
                      TestClass c;
                      return app.exec();
                    }
                    

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    1 Reply Last reply
                    1
                    • SPlattenS Offline
                      SPlattenS Offline
                      SPlatten
                      wrote on last edited by
                      #28

                      @Christian-Ehrlicher , what is your issue? You seem to be constantly on the attack. There is nothing plain old C++ about Qt.

                      I've been clear what I have done and what the results are. If it isn't working for me then it could be down to something else.

                      My development system:

                      macOS Catalina
                      Version 10.15.7
                      iMac (Retina 5K, 27-inch, Late 2015)
                      Processor 4 GHz Quad-Core Intel Core i7
                      Memory 16 GB 1867 MHz DDR3
                      Graphics AMD Radeon R9 M395X 4 GB
                      

                      Qt:

                      Qt Creator 4.13.2
                      Based on Qt 5.15.1 (Clang 11.0 (Apple), 64 bit)
                      Built on Oct 1 2020 01:16:46
                      From revision 2ee1af2032
                      

                      Qt Kits:

                      Desktop Qt 5.14.2 clang 64bit
                      Desktop Qt 5.15.0 clang 64bit
                      Qt 5.14.2 WebAssembly
                      Qt 5.14.2 for iOS
                      Qt 5.14.2 for iOS Simulator
                      Qt 5.15.0 WebAssembly
                      Qt 5.15.0 for iOS
                      Qt 5.15.0 for iOS Simulator
                      

                      I am using Desktop Qt 5.15.0 clang 64bit

                      Compiler

                      Clang (C++, x86 64bit in /usr/bin)
                      Clang (C++, x86 32bit in /ust/bin)
                      Apple Clang (armv7)
                      Apple Clang (x86_64)
                      Apple Clang (i386)
                      Apple Clang (armv7k)
                      Apple Clang (arm64)
                      

                      Kind Regards,
                      Sy

                      Christian EhrlicherC 1 Reply Last reply
                      0
                      • KroMignonK KroMignon

                        @SPlatten said in Is it possible to have pure virtual slots?:

                        QAbstractSocket::UnconnectedState
                        libc++abi.dylib: Pure virtual function called!

                        Have you take a look at stackoverflow?

                        For my understanding: yes it is possible

                        • on base class don't forget to add Q_OBJECT macro
                        • on subclass, do not add Q_SLOTS or slots for those slots
                        • and finally, don't forget to re-run moc if you change one of those things
                        SPlattenS Offline
                        SPlattenS Offline
                        SPlatten
                        wrote on last edited by
                        #29

                        @KroMignon The prototypes for both the base and derived classes were posted so you should see that the base includes Q_OBJECT macro.

                        Kind Regards,
                        Sy

                        1 Reply Last reply
                        0
                        • SPlattenS SPlatten

                          @Christian-Ehrlicher , what is your issue? You seem to be constantly on the attack. There is nothing plain old C++ about Qt.

                          I've been clear what I have done and what the results are. If it isn't working for me then it could be down to something else.

                          My development system:

                          macOS Catalina
                          Version 10.15.7
                          iMac (Retina 5K, 27-inch, Late 2015)
                          Processor 4 GHz Quad-Core Intel Core i7
                          Memory 16 GB 1867 MHz DDR3
                          Graphics AMD Radeon R9 M395X 4 GB
                          

                          Qt:

                          Qt Creator 4.13.2
                          Based on Qt 5.15.1 (Clang 11.0 (Apple), 64 bit)
                          Built on Oct 1 2020 01:16:46
                          From revision 2ee1af2032
                          

                          Qt Kits:

                          Desktop Qt 5.14.2 clang 64bit
                          Desktop Qt 5.15.0 clang 64bit
                          Qt 5.14.2 WebAssembly
                          Qt 5.14.2 for iOS
                          Qt 5.14.2 for iOS Simulator
                          Qt 5.15.0 WebAssembly
                          Qt 5.15.0 for iOS
                          Qt 5.15.0 for iOS Simulator
                          

                          I am using Desktop Qt 5.15.0 clang 64bit

                          Compiler

                          Clang (C++, x86 64bit in /usr/bin)
                          Clang (C++, x86 32bit in /ust/bin)
                          Apple Clang (armv7)
                          Apple Clang (x86_64)
                          Apple Clang (i386)
                          Apple Clang (armv7k)
                          Apple Clang (arm64)
                          
                          Christian EhrlicherC Online
                          Christian EhrlicherC Online
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by Christian Ehrlicher
                          #30

                          @SPlatten said in Is it possible to have pure virtual slots?:

                          If it isn't working for me then it could be down to something else.

                          No, it must be in your code. So do what we ask every time - provide a testcase which reproduce your problem.
                          And virtual functions and how they work is for sure c++ and not Qt.

                          /edit: and you should simply try out my example.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          SPlattenS 1 Reply Last reply
                          0
                          • Christian EhrlicherC Christian Ehrlicher

                            @SPlatten said in Is it possible to have pure virtual slots?:

                            If it isn't working for me then it could be down to something else.

                            No, it must be in your code. So do what we ask every time - provide a testcase which reproduce your problem.
                            And virtual functions and how they work is for sure c++ and not Qt.

                            /edit: and you should simply try out my example.

                            SPlattenS Offline
                            SPlattenS Offline
                            SPlatten
                            wrote on last edited by SPlatten
                            #31

                            @Christian-Ehrlicher , for the 2nd time today, hear is my code:

                            Base class prototype, just edited to move virtual slots out of public slot definitions:

                                class clsModHelper : public QTcpSocket {
                                Q_OBJECT
                            
                                protected:
                                    bool mblnExit;
                                    double mdblVersion;
                                    FILE* mfpDbgLog;
                                    qint64 mint64AppPID;
                                    std::thread* mpHeartbeat;
                                    std::thread* mpThread;
                                    static const int mscintConnectionTimeout;
                                    static const int mscintHeartbeatFrequency;
                                    static const char* mscpszHost;
                                    static clsModHelper* mspThis;
                                    static char msszTitle[MODULE_NAME_LENGTH + 1];
                                    quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
                            
                                    static bool blnToThisModule(clsJSON& objJSON);
                                    void cleanup();
                                    void loopUntilExit();
                                    void start();
                            
                                    virtual void onConnected() = 0;
                                    virtual void onDataIn() = 0;
                                    virtual void onDisconnected() = 0;
                            
                                public slots:
                                    void onErrorOccurred(QAbstractSocket::SocketError socketError);
                                    void onExitModule();
                                    void onKillThreads();
                            
                                public:
                                    static const char mscszAck[]
                                                   ,mscszCmdHB[]
                                                 ,mscszCommand[]
                                                ,mscszCommands[]
                                                   ,mscszError[]
                                                  ,mscszModule[]
                                                 ,mscszMsgType[]
                                                     ,mscszPID[]
                                                  ,mscszResult[]
                                                ,mscszSkipOver[]
                                                    ,mscszTime[]
                                                    ,mscszTrue[]
                                                    ,mscszType[]
                                                ,mscszTypeChar[]
                                              ,mscszTypeDouble[]
                                               ,mscszTypeFloat[]
                                                 ,mscszTypeInt[]
                                                ,mscszTypeLong[]
                                               ,mscszTypeShort[]
                                              ,mscszTypeString[]
                                               ,mscszTypeUChar[]
                                                ,mscszTypeUInt[]
                                               ,mscszTypeULong[]
                                              ,mscszTypeUShort[];      
                                    explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                         ,const char* cpszTitle, double dblVersion);
                                    virtual ~clsModHelper();
                                    double dblGetVersion() { return mdblVersion; }
                                    [[noreturn]] static void exitMsg(const char* cpszMsg
                                                                    ,const char* cpszPrefix = "ERROR"
                                                                    ,int intCode = EXIT_FAILURE);
                                    qint64 int64GetPID() { return mint64AppPID; }
                                    int intExitCode() { return 0; }
                                    static long lngTimeInSecs();
                                    static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                                    static const char* cpszGetTitle() { return msszTitle; }
                                    void queueJSON(QJsonObject& objJSON);
                                    void sendHeartbeat();
                                    void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                                    void threadBody();
                                    virtual void moduleThreadBody() = 0;
                                    quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
                            
                                signals:
                                    void onFailure(QJsonObject& objCmd);
                                    void onSuccess(QJsonObject& objCmd);
                                    void terminateModule();
                                    void threadTerminated();
                                };
                            

                            Derived class prototype:

                                class clsModFileIO : public clsModHelper {
                                private:
                                    static clsModFileIO* mspInstance;
                            
                                    void cmdLineSummary();
                            
                                public:
                                    static const char mscszCheck[]
                                                     ,mscszCmdFind[]
                                                     ,mscszCmdRead[]
                                                     ,mscszCmdSave[]
                                                     ,mscszCmdTell[]
                                                     ,mscszCmdWrite[]
                                                     ,mscszByteOrder[]
                                                     ,mscszData[]
                                                     ,mscszFailed[]
                                                     ,mscszFile[]
                                                     ,mscszFrom[]
                                                     ,mscszLength[]
                                                     ,mscszMode[]
                                                     ,mscszModeBinary[]
                                                     ,mscszModeText[]
                                                     ,mscszPattern[]
                                                     ,mscszPosition[]
                                                     ,mscszStart[]
                                                     ,mscszSuccess[];
                                    explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                                    ~clsModFileIO();
                                    bool doCommand(QString& strFile, QJsonObject& objRequest
                                                                   , QJsonObject& objCmd
                                                                   , QJsonObject& objResponse
                                                                   , quint16 uint16Idx = 0);        
                                    void moduleThreadBody() override;
                                    static clsModFileIO* pInstance() { return mspInstance; }
                            
                                    virtual void onConnected() override;
                                    virtual void onDataIn() override;
                                    virtual void onDisconnected() override;
                            
                                public slots:
                                    void onFailure(QJsonObject& objCmd);
                                    void onSuccess(QJsonObject& objCmd);
                                };
                            

                            With the code in this configuration the Application Output shows:

                            2020-11-06 18:04:44.443090+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onConnected() in ../mdFileIO/clsModHelper.cpp:67
                            2020-11-06 18:04:44.443120+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onDisconnected() in ../mdFileIO/clsModHelper.cpp:68
                            2020-11-06 18:04:44.443130+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onDataIn() in ../mdFileIO/clsModHelper.cpp:69
                            

                            As for a test case, I launch my main application which launches the problem application as a child process, immediately when this application is launched it attempts to connect to the launching application with a socket which is successful but the slots are not connected to the signals in QTcpSocket despite the connect statements being correct as far as I know.

                            Kind Regards,
                            Sy

                            B 1 Reply Last reply
                            0
                            • Christian EhrlicherC Online
                              Christian EhrlicherC Online
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by
                              #32

                              I can't compile it so no - that does not help. As you can see my example works as expected so it must be somewhere in your code. If you want help you have to provide something which we can reproduce which we can't.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              1 Reply Last reply
                              0
                              • SPlattenS SPlatten

                                @Christian-Ehrlicher , for the 2nd time today, hear is my code:

                                Base class prototype, just edited to move virtual slots out of public slot definitions:

                                    class clsModHelper : public QTcpSocket {
                                    Q_OBJECT
                                
                                    protected:
                                        bool mblnExit;
                                        double mdblVersion;
                                        FILE* mfpDbgLog;
                                        qint64 mint64AppPID;
                                        std::thread* mpHeartbeat;
                                        std::thread* mpThread;
                                        static const int mscintConnectionTimeout;
                                        static const int mscintHeartbeatFrequency;
                                        static const char* mscpszHost;
                                        static clsModHelper* mspThis;
                                        static char msszTitle[MODULE_NAME_LENGTH + 1];
                                        quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
                                
                                        static bool blnToThisModule(clsJSON& objJSON);
                                        void cleanup();
                                        void loopUntilExit();
                                        void start();
                                
                                        virtual void onConnected() = 0;
                                        virtual void onDataIn() = 0;
                                        virtual void onDisconnected() = 0;
                                
                                    public slots:
                                        void onErrorOccurred(QAbstractSocket::SocketError socketError);
                                        void onExitModule();
                                        void onKillThreads();
                                
                                    public:
                                        static const char mscszAck[]
                                                       ,mscszCmdHB[]
                                                     ,mscszCommand[]
                                                    ,mscszCommands[]
                                                       ,mscszError[]
                                                      ,mscszModule[]
                                                     ,mscszMsgType[]
                                                         ,mscszPID[]
                                                      ,mscszResult[]
                                                    ,mscszSkipOver[]
                                                        ,mscszTime[]
                                                        ,mscszTrue[]
                                                        ,mscszType[]
                                                    ,mscszTypeChar[]
                                                  ,mscszTypeDouble[]
                                                   ,mscszTypeFloat[]
                                                     ,mscszTypeInt[]
                                                    ,mscszTypeLong[]
                                                   ,mscszTypeShort[]
                                                  ,mscszTypeString[]
                                                   ,mscszTypeUChar[]
                                                    ,mscszTypeUInt[]
                                                   ,mscszTypeULong[]
                                                  ,mscszTypeUShort[];      
                                        explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                             ,const char* cpszTitle, double dblVersion);
                                        virtual ~clsModHelper();
                                        double dblGetVersion() { return mdblVersion; }
                                        [[noreturn]] static void exitMsg(const char* cpszMsg
                                                                        ,const char* cpszPrefix = "ERROR"
                                                                        ,int intCode = EXIT_FAILURE);
                                        qint64 int64GetPID() { return mint64AppPID; }
                                        int intExitCode() { return 0; }
                                        static long lngTimeInSecs();
                                        static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                                        static const char* cpszGetTitle() { return msszTitle; }
                                        void queueJSON(QJsonObject& objJSON);
                                        void sendHeartbeat();
                                        void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                                        void threadBody();
                                        virtual void moduleThreadBody() = 0;
                                        quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
                                
                                    signals:
                                        void onFailure(QJsonObject& objCmd);
                                        void onSuccess(QJsonObject& objCmd);
                                        void terminateModule();
                                        void threadTerminated();
                                    };
                                

                                Derived class prototype:

                                    class clsModFileIO : public clsModHelper {
                                    private:
                                        static clsModFileIO* mspInstance;
                                
                                        void cmdLineSummary();
                                
                                    public:
                                        static const char mscszCheck[]
                                                         ,mscszCmdFind[]
                                                         ,mscszCmdRead[]
                                                         ,mscszCmdSave[]
                                                         ,mscszCmdTell[]
                                                         ,mscszCmdWrite[]
                                                         ,mscszByteOrder[]
                                                         ,mscszData[]
                                                         ,mscszFailed[]
                                                         ,mscszFile[]
                                                         ,mscszFrom[]
                                                         ,mscszLength[]
                                                         ,mscszMode[]
                                                         ,mscszModeBinary[]
                                                         ,mscszModeText[]
                                                         ,mscszPattern[]
                                                         ,mscszPosition[]
                                                         ,mscszStart[]
                                                         ,mscszSuccess[];
                                        explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                                        ~clsModFileIO();
                                        bool doCommand(QString& strFile, QJsonObject& objRequest
                                                                       , QJsonObject& objCmd
                                                                       , QJsonObject& objResponse
                                                                       , quint16 uint16Idx = 0);        
                                        void moduleThreadBody() override;
                                        static clsModFileIO* pInstance() { return mspInstance; }
                                
                                        virtual void onConnected() override;
                                        virtual void onDataIn() override;
                                        virtual void onDisconnected() override;
                                
                                    public slots:
                                        void onFailure(QJsonObject& objCmd);
                                        void onSuccess(QJsonObject& objCmd);
                                    };
                                

                                With the code in this configuration the Application Output shows:

                                2020-11-06 18:04:44.443090+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onConnected() in ../mdFileIO/clsModHelper.cpp:67
                                2020-11-06 18:04:44.443120+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onDisconnected() in ../mdFileIO/clsModHelper.cpp:68
                                2020-11-06 18:04:44.443130+0000 mdFileIO[1591:37076] QObject::connect: No such slot clsModHelper::onDataIn() in ../mdFileIO/clsModHelper.cpp:69
                                

                                As for a test case, I launch my main application which launches the problem application as a child process, immediately when this application is launched it attempts to connect to the launching application with a socket which is successful but the slots are not connected to the signals in QTcpSocket despite the connect statements being correct as far as I know.

                                B Offline
                                B Offline
                                Bonnie
                                wrote on last edited by
                                #33

                                @SPlatten
                                You have some misunderstanding.
                                According to the SO post, the virtual functions need to be declared as slots in the base class, but not in the derived class.
                                So they still need to be in the "public slots" part of clsModHelper, but only "public" part of clsModFileIO.

                                And as I posted, the original way you use to connect (the new syntax) is fine to use.
                                The point is, the signals cannot be emited in the base class's constuctor.
                                As my testing, this is the most likely situation to cause that "Pure virtual function called!" error.
                                So if you put waitForConnected in clsModHelper's constructor, the connected signal will be emited in it and cause that error.

                                SPlattenS 1 Reply Last reply
                                1
                                • SPlattenS Offline
                                  SPlattenS Offline
                                  SPlatten
                                  wrote on last edited by
                                  #34

                                  The only way I can get rid of those messages is to move the prototypes back under the public slots area and then I get the original message:

                                  QAbstractSocket::UnconnectedState
                                  libc++abi.dylib: Pure virtual function called!
                                  

                                  I will try to produce a simple example and see if I can replicate the issue.

                                  Kind Regards,
                                  Sy

                                  1 Reply Last reply
                                  0
                                  • B Bonnie

                                    @SPlatten
                                    You have some misunderstanding.
                                    According to the SO post, the virtual functions need to be declared as slots in the base class, but not in the derived class.
                                    So they still need to be in the "public slots" part of clsModHelper, but only "public" part of clsModFileIO.

                                    And as I posted, the original way you use to connect (the new syntax) is fine to use.
                                    The point is, the signals cannot be emited in the base class's constuctor.
                                    As my testing, this is the most likely situation to cause that "Pure virtual function called!" error.
                                    So if you put waitForConnected in clsModHelper's constructor, the connected signal will be emited in it and cause that error.

                                    SPlattenS Offline
                                    SPlattenS Offline
                                    SPlatten
                                    wrote on last edited by SPlatten
                                    #35

                                    @Bonnie I'll give that a try. To clarify here is the implementation:

                                    clsModHelper::clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                              ,const char* cpszTitle, double dblVersion)
                                                : QTcpSocket(pParent)
                                                , mblnExit(false)
                                                , mdblVersion(dblVersion)
                                                , mfpDbgLog(nullptr)
                                                , mint64AppPID(QCoreApplication::applicationPid())
                                                , mpHeartbeat(nullptr), mpThread(nullptr)
                                                , muint16Port(0), muint16LauncherPID(0), muint16SleepTime(0) {    
                                        if ( intArgc < CLA_LAUNCHER_PID ) {
                                            std::cerr << "Insufficient arguments, aborting!";
                                            exit(EXIT_FAILURE);
                                        }
                                        if ( mspThis == nullptr ) {
                                            mspThis = this;
                                        }
                                        muint16Port = (quint16)atoi(parystrArgv[CLA_PORT]);
                                        muint16LauncherPID = (quint16)atoi(parystrArgv[CLA_LAUNCHER_PID]);
                                        //Connect up the signals
                                        connect(this, SIGNAL(connected()), this, SLOT(onConnected()));
                                        connect(this, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
                                        connect(this, SIGNAL(readyRead()), this, SLOT(onDataIn()));
                                        connect(this, &QAbstractSocket::errorOccurred, this, &clsModHelper::onErrorOccurred);
                                        //Module specific signals
                                        connect(this, &clsModHelper::terminateModule, this, &clsModHelper::onKillThreads);
                                        connect(this, &clsModHelper::threadTerminated, this, &clsModHelper::onExitModule);
                                        qdbg() << state();
                                        //Connect to the Application
                                        connectToHost(clsModHelper::mscpszHost, muint16Port);
                                    
                                        if ( waitForConnected(clsModHelper::mscintConnectionTimeout) ) {
                                        //Set-up title
                                            strcpy(msszTitle, cpszTitle);
                                        //Install custom message handler
                                            clsDebugService::serviceDebugQueue(msszTitle, true, true);
                                        //Build up title for output to the console
                                            char szTitle[MODULE_NAME_LENGTH + 24];
                                            sprintf(szTitle, "%s Version: %.2lf", cpszTitle, mdblVersion);
                                            qdbg() << szTitle;
                                        }
                                    }
                                    

                                    So now the base class prototype:

                                        class clsModHelper : public QTcpSocket {
                                        Q_OBJECT
                                    
                                        protected:
                                            bool mblnExit;
                                            double mdblVersion;
                                            FILE* mfpDbgLog;
                                            qint64 mint64AppPID;
                                            std::thread* mpHeartbeat;
                                            std::thread* mpThread;
                                            static const int mscintConnectionTimeout;
                                            static const int mscintHeartbeatFrequency;
                                            static const char* mscpszHost;
                                            static clsModHelper* mspThis;
                                            static char msszTitle[MODULE_NAME_LENGTH + 1];
                                            quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
                                    
                                            static bool blnToThisModule(clsJSON& objJSON);
                                            void cleanup();
                                            void loopUntilExit();
                                            void start();
                                    
                                        public slots:
                                            virtual void onConnected() = 0;
                                            virtual void onDataIn() = 0;
                                            virtual void onDisconnected() = 0;
                                            void onErrorOccurred(QAbstractSocket::SocketError socketError);
                                            void onExitModule();
                                            void onKillThreads();
                                    
                                        public:
                                            static const char mscszAck[]
                                                           ,mscszCmdHB[]
                                                         ,mscszCommand[]
                                                        ,mscszCommands[]
                                                           ,mscszError[]
                                                          ,mscszModule[]
                                                         ,mscszMsgType[]
                                                             ,mscszPID[]
                                                          ,mscszResult[]
                                                        ,mscszSkipOver[]
                                                            ,mscszTime[]
                                                            ,mscszTrue[]
                                                            ,mscszType[]
                                                        ,mscszTypeChar[]
                                                      ,mscszTypeDouble[]
                                                       ,mscszTypeFloat[]
                                                         ,mscszTypeInt[]
                                                        ,mscszTypeLong[]
                                                       ,mscszTypeShort[]
                                                      ,mscszTypeString[]
                                                       ,mscszTypeUChar[]
                                                        ,mscszTypeUInt[]
                                                       ,mscszTypeULong[]
                                                      ,mscszTypeUShort[];      
                                            explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                                 ,const char* cpszTitle, double dblVersion);
                                            virtual ~clsModHelper();
                                            double dblGetVersion() { return mdblVersion; }
                                            [[noreturn]] static void exitMsg(const char* cpszMsg
                                                                            ,const char* cpszPrefix = "ERROR"
                                                                            ,int intCode = EXIT_FAILURE);
                                            qint64 int64GetPID() { return mint64AppPID; }
                                            int intExitCode() { return 0; }
                                            static long lngTimeInSecs();
                                            static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                                            static const char* cpszGetTitle() { return msszTitle; }
                                            void queueJSON(QJsonObject& objJSON);
                                            void sendHeartbeat();
                                            void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                                            void threadBody();
                                            virtual void moduleThreadBody() = 0;
                                            quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
                                    
                                        signals:
                                            void onFailure(QJsonObject& objCmd);
                                            void onSuccess(QJsonObject& objCmd);
                                            void terminateModule();
                                            void threadTerminated();
                                        };
                                    

                                    And the derived prototype:

                                        class clsModFileIO : public clsModHelper {
                                        private:
                                            static clsModFileIO* mspInstance;
                                    
                                            void cmdLineSummary();
                                    
                                        public:
                                            static const char mscszCheck[]
                                                             ,mscszCmdFind[]
                                                             ,mscszCmdRead[]
                                                             ,mscszCmdSave[]
                                                             ,mscszCmdTell[]
                                                             ,mscszCmdWrite[]
                                                             ,mscszByteOrder[]
                                                             ,mscszData[]
                                                             ,mscszFailed[]
                                                             ,mscszFile[]
                                                             ,mscszFrom[]
                                                             ,mscszLength[]
                                                             ,mscszMode[]
                                                             ,mscszModeBinary[]
                                                             ,mscszModeText[]
                                                             ,mscszPattern[]
                                                             ,mscszPosition[]
                                                             ,mscszStart[]
                                                             ,mscszSuccess[];
                                            explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                                            ~clsModFileIO();
                                            bool doCommand(QString& strFile, QJsonObject& objRequest
                                                                           , QJsonObject& objCmd
                                                                           , QJsonObject& objResponse
                                                                           , quint16 uint16Idx = 0);        
                                            void moduleThreadBody() override;
                                            static clsModFileIO* pInstance() { return mspInstance; }
                                    
                                            virtual void onConnected() override;
                                            virtual void onDataIn() override;
                                            virtual void onDisconnected() override;
                                    
                                        public slots:
                                            void onFailure(QJsonObject& objCmd);
                                            void onSuccess(QJsonObject& objCmd);
                                        };
                                    

                                    With the code this way I get:

                                    QAbstractSocket::UnconnectedState
                                    libc++abi.dylib: Pure virtual function called!
                                    

                                    In the Application Output.

                                    Kind Regards,
                                    Sy

                                    B 1 Reply Last reply
                                    0
                                    • SPlattenS SPlatten

                                      @Bonnie I'll give that a try. To clarify here is the implementation:

                                      clsModHelper::clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                                ,const char* cpszTitle, double dblVersion)
                                                  : QTcpSocket(pParent)
                                                  , mblnExit(false)
                                                  , mdblVersion(dblVersion)
                                                  , mfpDbgLog(nullptr)
                                                  , mint64AppPID(QCoreApplication::applicationPid())
                                                  , mpHeartbeat(nullptr), mpThread(nullptr)
                                                  , muint16Port(0), muint16LauncherPID(0), muint16SleepTime(0) {    
                                          if ( intArgc < CLA_LAUNCHER_PID ) {
                                              std::cerr << "Insufficient arguments, aborting!";
                                              exit(EXIT_FAILURE);
                                          }
                                          if ( mspThis == nullptr ) {
                                              mspThis = this;
                                          }
                                          muint16Port = (quint16)atoi(parystrArgv[CLA_PORT]);
                                          muint16LauncherPID = (quint16)atoi(parystrArgv[CLA_LAUNCHER_PID]);
                                          //Connect up the signals
                                          connect(this, SIGNAL(connected()), this, SLOT(onConnected()));
                                          connect(this, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
                                          connect(this, SIGNAL(readyRead()), this, SLOT(onDataIn()));
                                          connect(this, &QAbstractSocket::errorOccurred, this, &clsModHelper::onErrorOccurred);
                                          //Module specific signals
                                          connect(this, &clsModHelper::terminateModule, this, &clsModHelper::onKillThreads);
                                          connect(this, &clsModHelper::threadTerminated, this, &clsModHelper::onExitModule);
                                          qdbg() << state();
                                          //Connect to the Application
                                          connectToHost(clsModHelper::mscpszHost, muint16Port);
                                      
                                          if ( waitForConnected(clsModHelper::mscintConnectionTimeout) ) {
                                          //Set-up title
                                              strcpy(msszTitle, cpszTitle);
                                          //Install custom message handler
                                              clsDebugService::serviceDebugQueue(msszTitle, true, true);
                                          //Build up title for output to the console
                                              char szTitle[MODULE_NAME_LENGTH + 24];
                                              sprintf(szTitle, "%s Version: %.2lf", cpszTitle, mdblVersion);
                                              qdbg() << szTitle;
                                          }
                                      }
                                      

                                      So now the base class prototype:

                                          class clsModHelper : public QTcpSocket {
                                          Q_OBJECT
                                      
                                          protected:
                                              bool mblnExit;
                                              double mdblVersion;
                                              FILE* mfpDbgLog;
                                              qint64 mint64AppPID;
                                              std::thread* mpHeartbeat;
                                              std::thread* mpThread;
                                              static const int mscintConnectionTimeout;
                                              static const int mscintHeartbeatFrequency;
                                              static const char* mscpszHost;
                                              static clsModHelper* mspThis;
                                              static char msszTitle[MODULE_NAME_LENGTH + 1];
                                              quint16 muint16Port, muint16LauncherPID, muint16SleepTime;
                                      
                                              static bool blnToThisModule(clsJSON& objJSON);
                                              void cleanup();
                                              void loopUntilExit();
                                              void start();
                                      
                                          public slots:
                                              virtual void onConnected() = 0;
                                              virtual void onDataIn() = 0;
                                              virtual void onDisconnected() = 0;
                                              void onErrorOccurred(QAbstractSocket::SocketError socketError);
                                              void onExitModule();
                                              void onKillThreads();
                                      
                                          public:
                                              static const char mscszAck[]
                                                             ,mscszCmdHB[]
                                                           ,mscszCommand[]
                                                          ,mscszCommands[]
                                                             ,mscszError[]
                                                            ,mscszModule[]
                                                           ,mscszMsgType[]
                                                               ,mscszPID[]
                                                            ,mscszResult[]
                                                          ,mscszSkipOver[]
                                                              ,mscszTime[]
                                                              ,mscszTrue[]
                                                              ,mscszType[]
                                                          ,mscszTypeChar[]
                                                        ,mscszTypeDouble[]
                                                         ,mscszTypeFloat[]
                                                           ,mscszTypeInt[]
                                                          ,mscszTypeLong[]
                                                         ,mscszTypeShort[]
                                                        ,mscszTypeString[]
                                                         ,mscszTypeUChar[]
                                                          ,mscszTypeUInt[]
                                                         ,mscszTypeULong[]
                                                        ,mscszTypeUShort[];      
                                              explicit clsModHelper(QObject* pParent, int intArgc, char* parystrArgv[]
                                                                   ,const char* cpszTitle, double dblVersion);
                                              virtual ~clsModHelper();
                                              double dblGetVersion() { return mdblVersion; }
                                              [[noreturn]] static void exitMsg(const char* cpszMsg
                                                                              ,const char* cpszPrefix = "ERROR"
                                                                              ,int intCode = EXIT_FAILURE);
                                              qint64 int64GetPID() { return mint64AppPID; }
                                              int intExitCode() { return 0; }
                                              static long lngTimeInSecs();
                                              static clsModHelper* psGetModuleInstance() { return clsModHelper::mspThis; }
                                              static const char* cpszGetTitle() { return msszTitle; }
                                              void queueJSON(QJsonObject& objJSON);
                                              void sendHeartbeat();
                                              void setSleepTime(quint16 uint16SleepTime) { muint16SleepTime = uint16SleepTime; }
                                              void threadBody();
                                              virtual void moduleThreadBody() = 0;
                                              quint16 uint16GetLauncherPID() { return muint16LauncherPID; }
                                      
                                          signals:
                                              void onFailure(QJsonObject& objCmd);
                                              void onSuccess(QJsonObject& objCmd);
                                              void terminateModule();
                                              void threadTerminated();
                                          };
                                      

                                      And the derived prototype:

                                          class clsModFileIO : public clsModHelper {
                                          private:
                                              static clsModFileIO* mspInstance;
                                      
                                              void cmdLineSummary();
                                      
                                          public:
                                              static const char mscszCheck[]
                                                               ,mscszCmdFind[]
                                                               ,mscszCmdRead[]
                                                               ,mscszCmdSave[]
                                                               ,mscszCmdTell[]
                                                               ,mscszCmdWrite[]
                                                               ,mscszByteOrder[]
                                                               ,mscszData[]
                                                               ,mscszFailed[]
                                                               ,mscszFile[]
                                                               ,mscszFrom[]
                                                               ,mscszLength[]
                                                               ,mscszMode[]
                                                               ,mscszModeBinary[]
                                                               ,mscszModeText[]
                                                               ,mscszPattern[]
                                                               ,mscszPosition[]
                                                               ,mscszStart[]
                                                               ,mscszSuccess[];
                                              explicit clsModFileIO(QObject* pParent, int intArgc, char* parystrArgv[]);
                                              ~clsModFileIO();
                                              bool doCommand(QString& strFile, QJsonObject& objRequest
                                                                             , QJsonObject& objCmd
                                                                             , QJsonObject& objResponse
                                                                             , quint16 uint16Idx = 0);        
                                              void moduleThreadBody() override;
                                              static clsModFileIO* pInstance() { return mspInstance; }
                                      
                                              virtual void onConnected() override;
                                              virtual void onDataIn() override;
                                              virtual void onDisconnected() override;
                                      
                                          public slots:
                                              void onFailure(QJsonObject& objCmd);
                                              void onSuccess(QJsonObject& objCmd);
                                          };
                                      

                                      With the code this way I get:

                                      QAbstractSocket::UnconnectedState
                                      libc++abi.dylib: Pure virtual function called!
                                      

                                      In the Application Output.

                                      B Offline
                                      B Offline
                                      Bonnie
                                      wrote on last edited by Bonnie
                                      #36

                                      @SPlatten
                                      That's exactly what I have guessed.
                                      So as I said I think it's better to not use waitForConnected() in clsModHelper's constructor.
                                      Calling a blocking function in a constructor is not a good design anyway.

                                      Christian EhrlicherC 1 Reply Last reply
                                      1
                                      • B Bonnie

                                        @SPlatten
                                        That's exactly what I have guessed.
                                        So as I said I think it's better to not use waitForConnected() in clsModHelper's constructor.
                                        Calling a blocking function in a constructor is not a good design anyway.

                                        Christian EhrlicherC Online
                                        Christian EhrlicherC Online
                                        Christian Ehrlicher
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #37

                                        @Bonnie said in Is it possible to have pure virtual slots?:

                                        Calling a blocking function in a constructor is not a good design anyway.

                                        Neither is calling a (pure) virtual function in the ctor/dtor.

                                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                        Visit the Qt Academy at https://academy.qt.io/catalog

                                        1 Reply Last reply
                                        1
                                        • SPlattenS Offline
                                          SPlattenS Offline
                                          SPlatten
                                          wrote on last edited by
                                          #38

                                          Here is the demo I just created and it works, so the problem has to be specific to the class:

                                              class clsBaseTest : public QObject {
                                              Q_OBJECT
                                          
                                              public slots:
                                                  //Pure virtual slot
                                                  virtual void onTest() = 0;
                                          
                                              public:
                                                  explicit clsBaseTest() {}
                                          
                                              signals:
                                                 void test();
                                              };
                                          
                                              class clsDerivedTest : public clsBaseTest {
                                              public:
                                                  clsDerivedTest() {}
                                          
                                                  virtual void onTest() override {
                                                      qDebug() << "clsDerivedTest::onTest";
                                                  };
                                              };
                                          

                                          Code to test:

                                              clsDerivedTest test;
                                              connect(&test, SIGNAL(test()), &test, SLOT(onTest()));
                                              emit test.test();
                                          

                                          In the Application Output I see exactly what I am supposed to see:

                                          2020-11-06 18:47:48.956472+0000 mdFileIO[3144:63052] clsDerivedTest::onTest
                                          

                                          So it must be the fact that the connections are established in the base class constructor, I will try moving these to another function.

                                          Kind Regards,
                                          Sy

                                          SPlattenS 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved