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. Deriving from QIODevice
Forum Updated to NodeBB v4.3 + New Features

Deriving from QIODevice

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

    Happy New Year!

    I would like to sub-class QFile to model a file that contains a hidden header. For this I wish all public read and write operations to be offset by the length of the hidden header. This seems ok except that in a couple of places QIODevice does not use the virtual method pos() internally and as a result my override of pos() that allows for the header is being ignored. For example in QIODevice::readAll() which is not virtual so I cannot properly override.

    Why is QIODevice not using the pos() virtual method internally, it seems to use size() and seek() as I would expect?

    1 Reply Last reply
    0
    • T Offline
      T Offline
      t3685
      wrote on last edited by
      #2

      Hi,

      Unless you really need to pass your class around as a QIODevice, an alternative would be to wrap a QFile inside your class instead of inheritance. QIODevice::readAll does not use pos for the simple reason that when someone calls read all, they expect everything to be read.

      B 1 Reply Last reply
      0
      • T t3685

        Hi,

        Unless you really need to pass your class around as a QIODevice, an alternative would be to wrap a QFile inside your class instead of inheritance. QIODevice::readAll does not use pos for the simple reason that when someone calls read all, they expect everything to be read.

        B Offline
        B Offline
        bsomervi
        wrote on last edited by bsomervi
        #3

        @t3685 Thanks for your comments.

        Passing the derived type as QIODevice * is absolutely necessary.

        Having readAll()return the hidden header is breaking the contract that the header is hidden! For example the non-hidden part is valid standing alone, the hidden header is metadata that is not necessary for a consumer or producer for the visible content. The metadata does explain the format of the data, but a client that knows or assumes the format does not need it. Regardless of that the metadata is exposed via other methods of the class.

        I have thought about delegating to QFile and having the public interface also derive from QIODevice but apart from having to forward many methods to the delegate I still see problems. I'll give it a try but it is a shame that QIODevice breaks its own contract by not using pos() when it should.

        BTW if QIODevice did use pos() there is no issue with a super-class that needs readAll() to read all, it would simply not override pos(), seek(), size() etc.. Surely this is the point of virtual base classes? Why are these methods virtual with default implementations if not for super-classes to "map" the actual position in the underlying media?

        1 Reply Last reply
        0
        • T Offline
          T Offline
          t3685
          wrote on last edited by t3685
          #4

          Hi,

          I don't know the requirements you have to fulfill, but I get the impression you are misunderstanding the design of QIODevice derived classes. These classes are meant to abstract the interaction with an IO device itself and do NOT represent any file format specific knowledge. Examples of io device derived classes are QTcpSocket or QSerialPort. These classes basically allow you to read/write data, any data to the device. Only member functions that are involved in this task are made virtual. For example pos() needs to be implemented differently for a socket and for a file, but read all should do the same.

          What you seem to be after is implementing a specific file type with a hidden header (note that none of the official derived classes even have notion of a header).

          So I think you are asking the wrong questions as to why some functions are virtual or and why some or not. Instead you should be asking yourself why am I making a new io device when I really need a file type implementation.

          B 2 Replies Last reply
          0
          • T t3685

            Hi,

            I don't know the requirements you have to fulfill, but I get the impression you are misunderstanding the design of QIODevice derived classes. These classes are meant to abstract the interaction with an IO device itself and do NOT represent any file format specific knowledge. Examples of io device derived classes are QTcpSocket or QSerialPort. These classes basically allow you to read/write data, any data to the device. Only member functions that are involved in this task are made virtual. For example pos() needs to be implemented differently for a socket and for a file, but read all should do the same.

            What you seem to be after is implementing a specific file type with a hidden header (note that none of the official derived classes even have notion of a header).

            So I think you are asking the wrong questions as to why some functions are virtual or and why some or not. Instead you should be asking yourself why am I making a new io device when I really need a file type implementation.

            B Offline
            B Offline
            bsomervi
            wrote on last edited by
            #5

            @t3685 said:

            So I think you are asking the wrong questions as to why some functions are virtual or and why some or not.

            No, I am specifically asking why QIODevice::readAll() a non-virtual member is using d->pos where it could and most definitely should be using pos(). If it did, thereby honoring the contract it promises by allowing pos() to be overridden, it would work just fine for me and everyone else.

            What I am trying to do is not really relevant, I am just asking why the implementation of QIODevice::readAll() is the way it is when a different, and IMHO, a correct implementation would use 'pos(). Your claim that readAll() should read everything is a straw man, what readAll() delivers should surely be determined by the sub-classes.

            1 Reply Last reply
            0
            • T t3685

              Hi,

              I don't know the requirements you have to fulfill, but I get the impression you are misunderstanding the design of QIODevice derived classes. These classes are meant to abstract the interaction with an IO device itself and do NOT represent any file format specific knowledge. Examples of io device derived classes are QTcpSocket or QSerialPort. These classes basically allow you to read/write data, any data to the device. Only member functions that are involved in this task are made virtual. For example pos() needs to be implemented differently for a socket and for a file, but read all should do the same.

              What you seem to be after is implementing a specific file type with a hidden header (note that none of the official derived classes even have notion of a header).

              So I think you are asking the wrong questions as to why some functions are virtual or and why some or not. Instead you should be asking yourself why am I making a new io device when I really need a file type implementation.

              B Offline
              B Offline
              bsomervi
              wrote on last edited by
              #6

              @t3685 said:

              Examples of io device derived classes are QTcpSocket or QSerialPort. These classes basically allow you to read/write data, any data to the device. Only member functions that are involved in this task are made virtual. For example pos() needs to be implemented differently for a socket and for a file, but read all should do the same.

              The difference between a socket and a file is modeled by QIODevice::isSequential(), that itself determines how pos() is used in other QIODevice methods.

              1 Reply Last reply
              0
              • T Offline
                T Offline
                t3685
                wrote on last edited by t3685
                #7

                readAll() violates no contracts as it does exactly what it promises, that is reading all data from a device. How it does that is an implementation detail.
                If you are 100% sure that you need to model your problem as a QIODevice and need readAll to behave differently you can always file a bug report.
                However I strongly recommend you look at other QIODevice implementations before doing so. Tcp packets and serial data might also have protocol information that does not need to shown to users. If that's the case you can see how they solved that problem.

                B 1 Reply Last reply
                0
                • T t3685

                  readAll() violates no contracts as it does exactly what it promises, that is reading all data from a device. How it does that is an implementation detail.
                  If you are 100% sure that you need to model your problem as a QIODevice and need readAll to behave differently you can always file a bug report.
                  However I strongly recommend you look at other QIODevice implementations before doing so. Tcp packets and serial data might also have protocol information that does not need to shown to users. If that's the case you can see how they solved that problem.

                  B Offline
                  B Offline
                  bsomervi
                  wrote on last edited by
                  #8

                  @t3685 said:

                  However I strongly recommend you look at other QIODevice implementations before doing so. Tcp packets and serial data might also have protocol information that does not need to shown to users. If that's the case you can see how they solved that problem.

                  I have written several QIODevice derivations and it is not a complex process. This is the first time that deriving from QFile seems so appropriate but given the impossibility of making it work like that I have aggregated a QFile object in my class that derives from QIODevice. It is working fine but I had to write may forwarding functions since my class needs all of the QFile API, but it is done now.

                  Thanks for your comments and suggestions.

                  Happy New Year!

                  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