2012-12-06 79 views
2

我有一個類Reader,它提供對二進制文件的訪問以對其執行讀取操作。Const方法臨時更改對象

該文件在同一文件中包含多個偏移量列表,其中要找到數據。這意味着,要獲得某些數據段,必須從某個位置讀取偏移量,然後跳轉到該偏移量,再次讀取偏移量,在那裏跳轉等,直到達到實際數據。

類認爲,在每次調用諸如

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

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

的方法,那些方法顯然不能const因爲它們的移動讀取位置調整讀取位置。

對於文件的幾個層次之間方便的導航中,類提供的堆疊,其中,根據需要可以壓入和彈出的偏移:

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 

那些壓入/彈出方法不能是const爲好,因爲它們改變偏移堆棧。

現在的問題是方便的方法,它應該從文件內部的已知位置提取數據。無論當前的閱讀位置如何,他們都必須工作,不要觸摸它。在設計上,他們應該是const,但這不起作用:

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

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

    popOffset(); 

    return data; 
} 

知道,這種方法會留下對象在相同的狀態,因爲它是調用前,但我仍然不能讓它const,因爲我在其中使用的每個方法都是非const

所以,我的問題是,什麼是最好的方法,當在一個「按設計」const方法臨時改變一個對象的狀態?

我想過const_cast<Reader*>(this),但這似乎是一種駭人聽聞的方法。或者你認爲在這種情況下是否合理?

+2

如果它是常量設計,那麼它是一個常量,不應該改變。如果它會被改變,那麼它不是一個常量。 –

+0

這種變化只發生在內部和臨時。該方法將確保返回時的最終對象狀態與用戶在調用之前的狀態「相同」。這就是我想通過將其標記爲'const'來顯示的內容。 – Dienes

+2

不正確,您無法驗證它會發生。代碼(或線程)可能會在您跳過並從文件中讀取後立即失敗。那麼對象本身處於不同的狀態(認爲多線程與邪惡的線程殺死其他線程)。 –

回答

1

您可以將位置字段mutable,然後將您的邏輯只讀方法標記爲const

如果你想保持pushOffsetpopOffset方法的公共API中,應該引入民間版本是const,並從readSomeDataFromKnownLocation方法中使用私有的。

+0

我不能讓位置'mutable'和讀取方法'const',因爲它們會根據當前位置給用戶帶來不同的結果,並且會改變後續調用的潛在結果。 – Dienes

+0

@Dienes我認爲讀取完成後,您的讀取方法正在恢復位置指示器。如果是這樣的話,他們如何改變隨後的呼叫? – vipw

+0

有兩種讀取方法:一種是每次調用都會提前讀取位置,另一種是隻能臨時移動讀取位置來檢索數據,但在返回之前恢復舊位置。後者取決於前者。 – Dienes