2012-12-03 114 views
0

我正在使用定義一些數據類型類的庫,通常以std :: vector <>的方式實現爲緊包裝。類型層次結構深數層,大多隻添加精細的構造函數。如何解決庫中的'const'定義

我的問題:基類定義它的std ::向量爲私有(這很好),但只添加一個訪問器方法爲const。派生類甚至無法訪問它。該庫看起來是這樣的(短爲清楚起見):

template <class T> class BaseList 
{ 
public: 
    BaseList (const T data0) : data_ (1) { 
     data_[0] = data0; } 

    const T & operator[] (const size_t nr) const { 
     // does out off bounds check here  
     return data_[nr]; } 

private: 
    std::vector<T> data_; 
} 

class FancyClass : public BaseList<SomeEnumType> 
{ 
public: 
    FancyClass (const SomeOtherEnumType data0) 
     : BaseList<SomeEnumType> (static_cast<SomeEnumType> (data)) 
     {} 
} 

現在我看到它時,常量的定義完全是僞造的。沒有內部方法依賴於矢量真的是不變的,我也不是在我的外部代碼中。

我喜歡做的事情很簡單:

strukt MyType { 
    FancyClass myData; 
    bool otherData; 
} 

int main() { 
    MyType storage = {FancyClass(0), false}; 

    storage.myData[0] = 5; 
} 

這當然不,因爲常量性的工作。 (「只讀位置的分配」)

完全在我身邊的責任:是否有一些const_cast魔術我可以做,使這個結構可寫? 我知道唯一的另一種可能性就是在我的代碼中完全複製類型層次結構,但是這仍然會讓我有很多強制轉換或toFancyClass()函數在我接口庫代碼時調用。

任何想法?謝謝!

(請不要在庫的代碼質量發表評論。如果我可以改變這種狀況,我就不會問這個問題...)

+3

那麼數據是由圖書館創建者有意將其設爲只讀。你爲什麼要改變它? –

+0

我們只是說我對「故意」部分不太確定。 –

回答

1

現在,我看到它,const定義完全是假的。沒有內部方法依賴於矢量真的是不變的,我也不是在我的外部代碼中。

方法上的const限定符並不意味着它依賴於常量的向量。這意味着該方法不會修改對象的狀態。它被添加以便下面的代碼將被編譯。

void f(const FancyClass a) 
{ 
    cout<<a[0]; 
} 

上面的代碼將不高於編譯而不對[]方法const的限定符。

不管怎樣,下面應該工作

SomeEnumType & r = const_cast<SomeEnumType &>(storage.myData[0]); 

r = b; 

其中b的類型是SomeEnumType

但是,如果你storage對象實際上是一個const對象,那麼就會導致未定義行爲的enum

+0

謝謝!這實際上編譯!但是,你究竟是什麼意思,實際上是一個const對象?底層向量不是,我的結構成員或我的「存儲」變量都不是。唯一的另一個const出現在構造函數參數列表中,但我認爲這不會使對象本身爲const,對吧? –

+0

@ Chaos_99 - 下面是'實際上是一個const對象'的示例 - http://stackoverflow.com/a/357607/922712但是這個例子是針對'char *'的。應該可以將該示例外推到類的const對象。例如。存儲變量可能是一個const對象,在這種情況下,這會導致未定義的行爲。 – user93353

1

最簡單的將是添加的非const版本的運營商[]。否則,您可能會通過使用const_cast來拋出常量來導致UB。

你可以扔掉這樣的常量性:

int main() { 
    MyType storage = {FancyClass(0), false}; 

    const_cast< SomeEnumType& >(storage.myData[0]) = 5; 
} 
+0

說:「類型'const SomeEnumType'中的無效const_cast'在我的代碼中輸入'FancyClass&' –

+1

@ Chaos_99:1.你不能通過const_cast改變類型2. BaseList => T == SomeEnumTypee,所以你必須轉換爲'SomeEnumType&'。 – MFH

+0

@ Chaos_99正確,固定。我沒有檢查在操作符中返回的是什麼類型[] –

0

通常operator []的進來對一個可變的和一個const版本。(請參見:Operator overloading

當然是有基於const_cast的解決方案,但它涉及到未定義的行爲(在拋棄常量之後,您不允許更改其值)

+1

Y您可以更改任何實際上不是const *的值*。消除這種不變或不會對此產生任何影響。 –

+0

基於N3485的§5.2.11.7,我試圖不同意'[注意:根據對象的類型,通過指針,左值或指針 對寫入操作產生的const_cast產生的數據成員, -qualifier73可能產生未定義的 行爲(7.1.6.1)。 - 注意]' – MFH

+0

是的,增加第二個可變運算符版本將是最好的解決方案。不幸的是,我不允許修改該庫的頭文件。我知道沒有辦法在我自己的源文件中添加它,尤其是因爲它需要爲基類定義,而不是我正在使用的'FancyClass'。 –

相關問題