2011-04-29 75 views
0

我有我的類常量,重載的方法:C++非const const的重載的方法選擇

class A{ 
    public: 
    typedef int data[10]; 

      data& operator[](int index); 
    const data& operator[](int index) const; 
} 

這個類實現寫入時複製了它的內部數據。我想,因爲我允許直接訪問數據,所以我必須在每次使用operator[]而不是operator[] const時創建共享數據的副本(如果它明顯共享)。但是,即使代碼使用operator []來讀取數據,但對象本身並沒有聲明爲const,它仍然會導致創建副本,因爲將使用operator []。有沒有什麼語法可以讓我選擇我打電話給哪些運營商?

+1

如果您允許人們保存返回的參考資料並在以後使用,那麼您必須在返回參考資料後禁用將來的共享。 – 2011-04-29 14:13:38

回答

2

是:const_cast<A const&>(anAObj)[5]

0

不,除非您將參考/指針轉換爲常量。或者創建一個不變的副本。

A a; 
const_cast<const A &> (a)[0] /*.foo()*/; 
+0

嗯,「不,除非」相當於「是」,不是嗎? ;) – ereOn 2011-04-29 14:06:04

+0

@ereOn:我認爲這取決於。在這種情況下,我的意思是聽起來更像是一個連接,突出了異常的可能性,而不是一個完善的規則,這意味着有這樣的語法,但是在代碼中使用它將不會讓用戶開心。實際上,我在回答寫回答時的想法是,我將實現具有不同接口的寫入時拷貝,其中數據代理始終保持不變,除非複製和基礎數據是可變的。但是這太想了,所以我決定簡單陳述「壞」的語法,並擺脫它,但你抓住了我:-D – 2011-04-29 14:16:52

1

爲什麼運營商返回一個data&而非int&引用單個項目?

話雖這麼說,你的選擇包括:

  • 永遠做哪怕原來是不需要的副本。
  • 使用操作員進行讀取或寫入,併爲另一個使用命名方法(例如GetRef)。
  • 在使用地點將對象投射到conststatic_cast<const A&>(obj)[index]
+0

我正在返回'數據&'所以我可以有支架操作符的二維數組他們在我的對象像'A a;''a [1] [2] = 3;'。 – 2011-04-29 14:19:16

0

實施data& at(size_t i);const data& cat(size_t);功能,這樣你就可以在非const對象調用cat()執行返回的數據常量性。

+0

這是我很樂意做的事情,如果不是我使用'operator []'的事實,並且因此不能向名稱添加字母或任何內容。 – 2011-04-29 14:17:49

1

您需要創建一個Proxy類來替代兩個方法的返回值。然後,在Proxy類中,您可以適當地處理讀取和寫入操作。這裏的代碼應該編譯驗證這個想法(與無符號整數數組工作):

typedef unsigned int UINT; 

類A {

class Proxy { 
public: 

    Proxy(const UINT &number): _number(number) {} 

    const Proxy &operator=(const Proxy &obj) { 
     cout << "Writting...\n"; 
     _number = obj._number; 
     return *this; 
    } 

    operator const UINT &() const { 
     cout << "Reading...\n"; 
     return _number; 
    } 

private: 

    UINT _number; 
}; 

市民:

A(UINT *array): _array(array) {} 

Proxy operator[](int index) { 
    return _array[index]; 
} 
const Proxy operator[](int index) const { 
    return _array[index]; 
} 

私人:

UINT *_array; 

};

INT主(INT ARGC,字符**的argv){

UINT myArray[] = {0, 1, 2, 3, 4}; 

A a(myArray);  // Normal A object 

UINT num1 = a[1]; // Reading fine 
a[1] = num1;   // Writting fine 

const A ca(myArray); // Constant A object 

UINT num2 = ca[1]; // Reading fine 
ca[1] = num2;  // Writting NOT fine (compilation error) 

return 0; 

}

+0

想法很好,但是從我的代碼中可以看到,我希望可以使它與多維數組一起工作 - 它仍然是可能的,但隨着維數的增長,它變得凌亂,似乎不容易泛化到n維。 (用我的方法,我可以將數據輸入爲n-1維數組,然後將我的對象視爲n維數組)。 – 2011-06-12 02:02:27

0

如果要實現寫入時複製,那麼你不應該在所有定義這些訂閱的運營商。如果客戶端調用對象x的訂閱方法的const版本,則不允許隨後使用該引用修改x的組件,但引用仍應反映其他客戶端對該組件的更改(該組件)x。但是他的寫作策略是不會發生的,因爲這種變化將發生在與參考點不同的副本上。

另外兩個調用具有相同索引的非const訂閱操作符的客戶端應獲得(可修改的)對的相同引用data對象;但他們不會,因爲在訂閱操作員被調用時會創建兩個單獨的副本。

取而代之,您可以使用按值返回data的訂閱方法。這避免了創建獲得x的組件的別名的錯覺(正如我認爲必須是當寫入複製被實現時的虛幻)。您還可以提供一種修改x組件的單一方法(而不是將此操作拆分爲訂閱,然後將其分配給所獲得的引用),該方法可以在內部創建副本,也可以僅在此副本上修改組件已經制成。這會隱藏客戶端使用寫入時複製實現。

更一般地說,暴露返回對內部對象的引用的方法,不管const是否暴露了這些對象完全存在的實現細節。這限制了稍後更改實現的自由度,例如壓縮數據或將其存儲在其他地方而不是內存中。

相關問題