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?

Is it possible to have pure virtual slots?

Scheduled Pinned Locked Moved Solved General and Desktop
39 Posts 6 Posters 7.4k 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 Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I have a based class which creates several slots:

    virtual void connected() = 0;
    virtual void dataIn() = 0;
    virtual void disconnected() = 0;
    

    In my derived class I implement these slots:

    void connected() override;
    void dataIn() override;
    void disconnected() override;
    

    I'm asking if this is possible because since I've done this I'm getting some very odd behaviour which I cannot explain, execution is halting in internal Qt functions.

    [Edit] I just read here:
    https://stackoverflow.com/questions/2998216/does-qt-support-virtual-pure-slots

    That the answer is yes, but the override keyword is not required and the driver functions should not appear under a public slots section...but having done that I'm still getting:

    'function name' overrides a member function but is not marked 'override' 
    

    For each overridden slot, this does not explain the strange behaviour.

    Kind Regards,
    Sy

    1 Reply Last reply
    0
    • SPlattenS SPlatten

      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.

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

      @SPlatten , I moved the socket connection from the constructor to its own function:

      void clsModHelper::connectToXMLMPAM() {
          //Connect to the Application
          connectToHost(clsModHelper::mscpszHost, muint16Port);
      
          if ( waitForConnected(clsModHelper::mscintConnectionTimeout) != true ) {
              throw -1;
          }
      }
      

      main loops like this:

      int main(int intArgc, char* parystrArgv[]) {
      //Initialise the module                
          QApplication a(intArgc, parystrArgv);
          clsModFileIO obj(&a, intArgc, parystrArgv);
      
          try{
              obj.connectToXMLMPAM();
          } catch( exception& e) {
              std::cout << "Could not connect to XMLMPAM!";
              exit(EXIT_FAILURE);
          }
          return obj.intExitCode();
      }
      

      Now it works, thank you to everyone who helped me to resolve this issue.

      Kind Regards,
      Sy

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        What strange behavior do you get ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        SPlattenS 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          What strange behavior do you get ?

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

          @SGaist I had a break point on:

          if ( waitForConnected(clsModHelper::mscintConnectionTimeout) ) {
          

          I've set the mscintConnectionTimeout to 20000 ms. When I click on the step over icon, the debugger jumps into qobjectdefs_impl.h and stops on line 152:

          (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
          

          Kind Regards,
          Sy

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            What if you have a pure virtual with a default implementation ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            SPlattenS 3 Replies Last reply
            0
            • SGaistS SGaist

              What if you have a pure virtual with a default implementation ?

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

              @SGaist, can you please explain what you mean? I'm not sure I understand.

              Found this:
              https://rvarago.medium.com/default-implementation-for-pure-virtual-functions-in-c-3c525cc820af

              Will give it a try tomorrow.

              Kind Regards,
              Sy

              1 Reply Last reply
              0
              • SGaistS SGaist

                What if you have a pure virtual with a default implementation ?

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

                @SGaist All the pure virtual functions have overloaded methods in the derived class or the derived class would be abstract. Presently these are very simple functions and just contain a qDebug() << "function name" entry.

                Kind Regards,
                Sy

                1 Reply Last reply
                0
                • SGaistS SGaist

                  What if you have a pure virtual with a default implementation ?

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

                  @SGaist , updated....if I comment out the 3 connects which:

                  //    connect(this, &QTcpSocket::connected, this, &clsModHelper::connected);
                  //    connect(this, &QTcpSocket::disconnected, this, &clsModHelper::disconnected);
                  //    connect(this, &QIODevice::readyRead, this, &clsModHelper::dataIn);
                  

                  It doesn't crash and the connection is made, waitForConnected doesn't crash and the application continues to where I expect.

                  To clarify, in the base class, the initial prototype for these slots:

                      public slots:
                          virtual void connected() = 0;
                          virtual void dataIn() = 0;
                          virtual void disconnected() = 0;
                  

                  Then in my derived class:

                      public slots:
                          void connected() override;
                          void dataIn() override;
                          void disconnected() override;
                  

                  The implementation, just to prove if works:

                  void clsModFileIO::connected() {
                      //Start the module thread
                      start();
                  }
                  void clsModFileIO::dataIn() {
                      qdbg() << "dataIn";
                  }
                  void clsModFileIO::disconnected() {
                      emit terminateModule();
                  }
                  

                  If I then uncomment those connections and rebuild it does exactly the same its very repeatable.

                  Kind Regards,
                  Sy

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

                    I used to have pure virtual slots. It's quite a long time ago so I was using the old syntax to connect. Maybe you can try if that will work.
                    P.S. I think the "override" mark is irrelevant, you can add that. The SO post is so old that c++11 was not published at that time.

                    SPlattenS 3 Replies Last reply
                    0
                    • B Bonnie

                      I used to have pure virtual slots. It's quite a long time ago so I was using the old syntax to connect. Maybe you can try if that will work.
                      P.S. I think the "override" mark is irrelevant, you can add that. The SO post is so old that c++11 was not published at that time.

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

                      @Bonnie , thank you, the only reason I put in the override keyword is to get rid of the annoying yellow text appended at the end of each line suggesting it.

                      Kind Regards,
                      Sy

                      J.HilkJ 1 Reply Last reply
                      0
                      • SPlattenS SPlatten

                        @Bonnie , thank you, the only reason I put in the override keyword is to get rid of the annoying yellow text appended at the end of each line suggesting it.

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

                        @SPlatten is clsModHelper the base class of clsModFileIO?


                        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.

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

                          @SPlatten is clsModHelper the base class of clsModFileIO?

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

                          @J-Hilk Yes

                          Kind Regards,
                          Sy

                          J.HilkJ 1 Reply Last reply
                          0
                          • B Bonnie

                            I used to have pure virtual slots. It's quite a long time ago so I was using the old syntax to connect. Maybe you can try if that will work.
                            P.S. I think the "override" mark is irrelevant, you can add that. The SO post is so old that c++11 was not published at that time.

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

                            @Bonnie , just replaced connections with:

                                connect(this, SIGNAL(connected), this, SLOT(connected));
                                connect(this, SIGNAL(disconnected), this, SLOT(disconnected));
                                connect(this, SIGNAL(readyRead), this, SLOT(dataIn));
                            

                            It worked, no more crashing, thank you.

                            Kind Regards,
                            Sy

                            1 Reply Last reply
                            0
                            • SPlattenS SPlatten

                              @J-Hilk Yes

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

                              @SPlatten ok, than this
                              connect(this, &QTcpSocket::connected, this, &clsModHelper::connected);

                              is explicitly invoking the pure virtual base function, thats bound to crash

                              connect(this, &QTcpSocket::connected, this, & clsModFileIO::connected);

                              should work fine


                              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.

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

                                @SPlatten ok, than this
                                connect(this, &QTcpSocket::connected, this, &clsModHelper::connected);

                                is explicitly invoking the pure virtual base function, thats bound to crash

                                connect(this, &QTcpSocket::connected, this, & clsModFileIO::connected);

                                should work fine

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

                                @J-Hilk , thank you, but isn't this the point of using a pure virtual slot, I want the actual derived slot to be worked out by the compiler so I can have any number of derived classes based the same pure virtual slot and then the actual slot gets called in its place?

                                Kind Regards,
                                Sy

                                J.HilkJ 1 Reply Last reply
                                0
                                • B Bonnie

                                  I used to have pure virtual slots. It's quite a long time ago so I was using the old syntax to connect. Maybe you can try if that will work.
                                  P.S. I think the "override" mark is irrelevant, you can add that. The SO post is so old that c++11 was not published at that time.

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

                                  @Bonnie , not so fast, I thought it worked because it didn't crash, but now I see in the Application Output:

                                  2020-11-06 09:11:49.460550+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::connected in ../mdFileIO/clsModHelper.cpp:67
                                  2020-11-06 09:11:49.460576+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::disconnected in ../mdFileIO/clsModHelper.cpp:68
                                  2020-11-06 09:11:49.460583+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::readyRead in ../mdFileIO/clsModHelper.cpp:69
                                  

                                  Kind Regards,
                                  Sy

                                  B 1 Reply Last reply
                                  0
                                  • SPlattenS SPlatten

                                    @Bonnie , not so fast, I thought it worked because it didn't crash, but now I see in the Application Output:

                                    2020-11-06 09:11:49.460550+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::connected in ../mdFileIO/clsModHelper.cpp:67
                                    2020-11-06 09:11:49.460576+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::disconnected in ../mdFileIO/clsModHelper.cpp:68
                                    2020-11-06 09:11:49.460583+0000 mdFileIO[4406:86031] QObject::connect: Parentheses expected, signal clsModHelper::readyRead in ../mdFileIO/clsModHelper.cpp:69
                                    
                                    B Offline
                                    B Offline
                                    Bonnie
                                    wrote on last edited by Bonnie
                                    #16

                                    @SPlatten
                                    The old syntax is not like that :)
                                    As the output says you need parentheses like

                                        connect(this, SIGNAL(connected()), this, SLOT(connected()));
                                        connect(this, SIGNAL(disconnected()), this, SLOT(disconnected()));
                                        connect(this, SIGNAL(readyRead()), this, SLOT(dataIn()));
                                    
                                    SPlattenS 1 Reply Last reply
                                    1
                                    • B Bonnie

                                      @SPlatten
                                      The old syntax is not like that :)
                                      As the output says you need parentheses like

                                          connect(this, SIGNAL(connected()), this, SLOT(connected()));
                                          connect(this, SIGNAL(disconnected()), this, SLOT(disconnected()));
                                          connect(this, SIGNAL(readyRead()), this, SLOT(dataIn()));
                                      
                                      SPlattenS Offline
                                      SPlattenS Offline
                                      SPlatten
                                      wrote on last edited by
                                      #17

                                      @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!
                                      

                                      Kind Regards,
                                      Sy

                                      B 1 Reply Last reply
                                      0
                                      • SPlattenS SPlatten

                                        @J-Hilk , thank you, but isn't this the point of using a pure virtual slot, I want the actual derived slot to be worked out by the compiler so I can have any number of derived classes based the same pure virtual slot and then the actual slot gets called in its place?

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

                                        @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.


                                        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.

                                        SPlattenS 1 Reply Last reply
                                        0
                                        • 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

                                            • Login

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