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. Subclassing items in a model

Subclassing items in a model

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 2 Posters 707 Views 1 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    My app has several models, built following the example in the video on this page. They all work fine, but now one of them needs to maintain a list of (pointers to) dissimilar items.

    The base class for the list members is Equipment (a struct). I've created a subclass called Vsp. I'm not sure how to go about writing the data()/setData() functions for this. I tried writing a data() routine for both the parent and subclass, as well as a dataSubclass() routine. The idea was to declare dataSubclass as a pure virtual function in the parent class, but doing so renders the class abstract, so I can't instantiate from it.

    I want the parent class to do some work, as there are properties that are common to all subclasses, and I don't want to replicate the common code in all the subclasses. Before I disappear down the rabbit hole, can someone advise on whether I'm on the right track, or if there's a better way to do this that I'm not aware of.

    Thanks for any suggestions...

    JonBJ 1 Reply Last reply
    0
    • mzimmersM mzimmers

      @JonB thanks for the input. Along the lines of your latter suggestion, I've done this:

      QVariant EquipmentModel::data(const QModelIndex &index, int role) const
      {
          QVariant qv = QVariant();
          Equipment &equipment = *(*m_list)[index.row()];
      
          qv = equipment.data(role);
          if (!qv.isValid()) {
              qv = equipment.dataSubclass(role);
          }
      

      where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

      This isn't really a necessary feature, I suppose - I could put all the roles for all the subclasses in my model. The concern there is performance -- the data() function gets called a lot in this design.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #4

      @mzimmers said in Subclassing items in a model:

      where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

      I don't know what you mean here about requiring pure virtual. You can make it that if you wish --- like you said, will make the class abstract --- but override is just as applicable once virtual whether pure or not. You can provide a base/default implementation which does nothing, then those subclasses which choose to override it can provide an alternative as appropriate. "If I don't make it pure virtual, I don't know how to get the override functions to be called." --- you have something wrong if you find this is the case.

      mzimmersM 1 Reply Last reply
      1
      • mzimmersM mzimmers

        Hi all -

        My app has several models, built following the example in the video on this page. They all work fine, but now one of them needs to maintain a list of (pointers to) dissimilar items.

        The base class for the list members is Equipment (a struct). I've created a subclass called Vsp. I'm not sure how to go about writing the data()/setData() functions for this. I tried writing a data() routine for both the parent and subclass, as well as a dataSubclass() routine. The idea was to declare dataSubclass as a pure virtual function in the parent class, but doing so renders the class abstract, so I can't instantiate from it.

        I want the parent class to do some work, as there are properties that are common to all subclasses, and I don't want to replicate the common code in all the subclasses. Before I disappear down the rabbit hole, can someone advise on whether I'm on the right track, or if there's a better way to do this that I'm not aware of.

        Thanks for any suggestions...

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #2

        @mzimmers
        I am not as expert as some here on C++, or the "right" way to do things (nowadays). For example some might tell you to approach this via templates, I don't know. But there are two obvious ways you can tackle this in a class-inheriting language:

        • Define a base method which does the "common" code. Make it virtual, but document to developers that any override is required to call the base method as well as whatever else it might do.

        • Define a base method which does the common code, this time not virtual, but put into it an "extra" call to some other base method. Make that method virtual but not pure (so not making it abstract) and have the base class supply a definition which does nothing. Developers override that extra base method only to do their extras.

        Qt uses both of these strategies at various points.

        mzimmersM 1 Reply Last reply
        0
        • JonBJ JonB

          @mzimmers
          I am not as expert as some here on C++, or the "right" way to do things (nowadays). For example some might tell you to approach this via templates, I don't know. But there are two obvious ways you can tackle this in a class-inheriting language:

          • Define a base method which does the "common" code. Make it virtual, but document to developers that any override is required to call the base method as well as whatever else it might do.

          • Define a base method which does the common code, this time not virtual, but put into it an "extra" call to some other base method. Make that method virtual but not pure (so not making it abstract) and have the base class supply a definition which does nothing. Developers override that extra base method only to do their extras.

          Qt uses both of these strategies at various points.

          mzimmersM Offline
          mzimmersM Offline
          mzimmers
          wrote on last edited by
          #3

          @JonB thanks for the input. Along the lines of your latter suggestion, I've done this:

          QVariant EquipmentModel::data(const QModelIndex &index, int role) const
          {
              QVariant qv = QVariant();
              Equipment &equipment = *(*m_list)[index.row()];
          
              qv = equipment.data(role);
              if (!qv.isValid()) {
                  qv = equipment.dataSubclass(role);
              }
          

          where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

          This isn't really a necessary feature, I suppose - I could put all the roles for all the subclasses in my model. The concern there is performance -- the data() function gets called a lot in this design.

          JonBJ 1 Reply Last reply
          0
          • mzimmersM mzimmers

            @JonB thanks for the input. Along the lines of your latter suggestion, I've done this:

            QVariant EquipmentModel::data(const QModelIndex &index, int role) const
            {
                QVariant qv = QVariant();
                Equipment &equipment = *(*m_list)[index.row()];
            
                qv = equipment.data(role);
                if (!qv.isValid()) {
                    qv = equipment.dataSubclass(role);
                }
            

            where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

            This isn't really a necessary feature, I suppose - I could put all the roles for all the subclasses in my model. The concern there is performance -- the data() function gets called a lot in this design.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #4

            @mzimmers said in Subclassing items in a model:

            where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

            I don't know what you mean here about requiring pure virtual. You can make it that if you wish --- like you said, will make the class abstract --- but override is just as applicable once virtual whether pure or not. You can provide a base/default implementation which does nothing, then those subclasses which choose to override it can provide an alternative as appropriate. "If I don't make it pure virtual, I don't know how to get the override functions to be called." --- you have something wrong if you find this is the case.

            mzimmersM 1 Reply Last reply
            1
            • JonBJ JonB

              @mzimmers said in Subclassing items in a model:

              where my dataSubclass() method is pure virtual. The intent was to override it in each subclass. If I don't make it pure virtual, I don't know how to get the override functions to be called.

              I don't know what you mean here about requiring pure virtual. You can make it that if you wish --- like you said, will make the class abstract --- but override is just as applicable once virtual whether pure or not. You can provide a base/default implementation which does nothing, then those subclasses which choose to override it can provide an alternative as appropriate. "If I don't make it pure virtual, I don't know how to get the override functions to be called." --- you have something wrong if you find this is the case.

              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by
              #5

              Oh, excellent! So...how does the compiler/OS know that, when I hit the equipment.dataSubclass() line above, that I want to invoke the method in the subclass, and not the (empty) method in the parent class? Is this part of the magic of polymorphism?

              JonBJ 1 Reply Last reply
              0
              • mzimmersM mzimmers

                Oh, excellent! So...how does the compiler/OS know that, when I hit the equipment.dataSubclass() line above, that I want to invoke the method in the subclass, and not the (empty) method in the parent class? Is this part of the magic of polymorphism?

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #6

                @mzimmers said in Subclassing items in a model:

                that I want to invoke the method in the subclass, and not the (empty) method in the parent class?

                That is what declaring the method virtual does. Overriders can use override --- and I suggest they always do --- but that does not actually matter, it's a compiler check. The original virtual causes the behaviour.

                pure virtual has the above behaviour, but does not even supply a default implementation. It must be sub-classed and that method must be defined/overridden.

                C++ executes all this though class vtables and suitable compile-time optimisation to make it efficient. Other languages do whatever equivalent.

                The automatic calling of the overridden derived methods comes with inheritance. So far as I know, polymorphism refers to multiple inheritance. Some O/O languages support this, some do not. C++ does. Your classes can inherit/derive from several classes. Some Qt classes are defined like this. But that is not directly relevant to virtual, except that there are rules about which to call if more than one inherited class has the same method name, so an override is ambiguous. But that is a specific detail case.

                mzimmersM 1 Reply Last reply
                1
                • JonBJ JonB

                  @mzimmers said in Subclassing items in a model:

                  that I want to invoke the method in the subclass, and not the (empty) method in the parent class?

                  That is what declaring the method virtual does. Overriders can use override --- and I suggest they always do --- but that does not actually matter, it's a compiler check. The original virtual causes the behaviour.

                  pure virtual has the above behaviour, but does not even supply a default implementation. It must be sub-classed and that method must be defined/overridden.

                  C++ executes all this though class vtables and suitable compile-time optimisation to make it efficient. Other languages do whatever equivalent.

                  The automatic calling of the overridden derived methods comes with inheritance. So far as I know, polymorphism refers to multiple inheritance. Some O/O languages support this, some do not. C++ does. Your classes can inherit/derive from several classes. Some Qt classes are defined like this. But that is not directly relevant to virtual, except that there are rules about which to call if more than one inherited class has the same method name, so an override is ambiguous. But that is a specific detail case.

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #7

                  @JonB yeah, I did a little reading on the override "operator" or whatever it is - I guess it's not necessary (as you said); someone referred to it as "syntactic sugar." But I can see the value in using it here, so the compiler will catch any mistakes.

                  And yeah, this seems to be more a feature of inheritance than polymorphism. It's still not clear to me how the program knows not to call the base class method (which, while it does nothing, still does exist) and instead invoke the appropriate subclass method. But I guess I'll just trust it.

                  Thanks for the recommendation and the clarification.

                  JonBJ 1 Reply Last reply
                  0
                  • mzimmersM mzimmers has marked this topic as solved on
                  • mzimmersM mzimmers

                    @JonB yeah, I did a little reading on the override "operator" or whatever it is - I guess it's not necessary (as you said); someone referred to it as "syntactic sugar." But I can see the value in using it here, so the compiler will catch any mistakes.

                    And yeah, this seems to be more a feature of inheritance than polymorphism. It's still not clear to me how the program knows not to call the base class method (which, while it does nothing, still does exist) and instead invoke the appropriate subclass method. But I guess I'll just trust it.

                    Thanks for the recommendation and the clarification.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #8

                    @mzimmers said in Subclassing items in a model:

                    It's still not clear to me how the program knows not to call the base class method (which, while it does nothing, still does exist) and instead invoke the appropriate subclass method. But I guess I'll just trust it.

                    Have a read of just the first couple of paragraphs of Wikipedia's Virtual method table. In C++ when an object is created it gains access to a table of pointers to functions specific to its class, including dealing with virtual/overrides.

                    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