Domanda

I have a class Reader which provides access to a binary file to perform read operations on it.

This file contains several lists of offsets within the same file, where data is to be found. This means that, to get to certain data segments, one has to read an offset from some position, then jump to that offset, read an offset again, jump there, etc. until finally you reach the actual data.

The class maintains a reading position that is adjusted each time you call a method like

// reads 4 bytes and advances the position by 4 bytes
uint32 Reader::readOffset() { /* */ } 

or

// moves the position to offset
void Reader::jumpTo(uint32 offset) { /* */ }

Those methods obviously cannot be const as they are moving the reading position.

For convenient navigation between several levels of the file, the class provides a stack, where one can push and pop offsets as needed:

uint32 someOffset = reader.readOffset();
reader.pushOffset(); // remember position
reader.jumpTo(someOffset); // do something on another position
reader.popOffset(); // go back to where we were before

Those push/pop methods cannot be const as well, because they alter the offset stack.

The problem now is with convenience methods, that are supposed to extract data from an internally known position within the file. They have to work regardless of the current reading position and should not touch it. By design, they ought to be const, but this does not work:

uint32 Reader::readSomeDataFromKnownLocation() const
{
    pushOffset();

    jumpTo(1234ul);
    uint32 data = readData();

    popOffset();

    return data;
}

I do know that this method will leave the object in the same state as it was before the call, but still I cannot make it const because each and every method I use within it is non-const.

So, my question is, what is the best approach when having to temporarily change an object's state within a "by-design" const method?

I thought about const_cast<Reader*>(this) but this seems like a hackish approach. Or do you think it is justified in this scenario?

È stato utile?

Soluzione

You can make the position field mutable and then mark your logically read only methods as const.

If you want to keep the pushOffset and popOffset methods in the public API, you should introduce private versions that are const, and use the private ones from within your readSomeDataFromKnownLocation method.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top