2012-12-13 109 views
6

我正在使用一個成員變量,並且在程序的某個點上我想更改它,但我更喜歡在其他地方「鎖定」它以防止意外更改。變量是否可以鎖定以防止在C++中對其進行更改?

代碼解釋:

class myClass { 
    int x; // This should be prevented to being changed most of the time 
    int y; // Regular variable 
    myclass() {x = 1;} 
    void foo1() {x++; y++;} // This can change x 
    void foo2() {x--; y--;} // This shouldn't be able to change x 
          // I want it to throw a compile error 
}; 

的問題是:它可以以某種方式實現?像永久const_cast的東西?

我知道我可以使用構造函數初始化列表和常量,但我需要稍後更改我的變量。

+2

使它變得私密,只有當你想要時才改變它? – Chad

+0

你想阻止實現改變x,還是你想阻止任何人調用該方法? – Joe

+0

@Joe:我想在編譯時拋出一個錯誤。 – Petr

回答

2

好的,我不喜歡的所有其他答案,所以這裏是我的想法:隱藏變量。

#define READONLY(TYPE, VAR) const TYPE& VAR = this->VAR //C++03 
#define READONLY(VARIABLE) const auto& VARIABLE = this->VARIABLE //C++11 

class myClass { 
    int x; // This should be prevented to being changed most of the time 
    int y; // Regular variable 
    myClass() :x(1), y(2) {} 
    void foo1() {// This can change x 
     x++; 
     y++; 
    } 
    void foo2() {// This shouldn't be able to change x 
     READONLY(x); //in this function, x is read-only 
     x++; //error: increment of read-only variable 'x' 
     y++; 
    } 
}; 

還是有辦法繞過變量(如this->x)的鎖定,但是沒有什麼可以對這些情況進行。

+0

對我來說,如果你打算這樣做,你需要像'#define lock(v)const auto&v = this-> v'這樣的東西,所以在函數中顯示爲'lock(x);/* ... * /'。模板可能會讓你更乾淨地做同樣的事情。 –

+0

如果我想防止在一個函數中進行編輯,那麼這是一個很好的解決方案,但是我可以通常阻止它嗎? – Petr

+1

@Petr:即使在理論上也沒有辦法推廣。在這個問題中,你有評論告訴_us_哪些變量被鎖定在哪些函數中。編譯器將需要相同的一般信息。在_any_函數中很容易使其不可編輯,但如果某些函數可編輯,則必須告訴我們/編譯器哪些函數。 –

0

那麼你不能做你想做的事... 有人糾正我,如果我錯了。

+1

他希望'foo1'改變x,但不是'foo2' – Chad

+0

@benjarobin:變量可以通過隱藏它們來鎖定 –

+0

@Minging Duck:但是如果我隱藏它(不管是什麼意思),我可以用它來只讀目的是在別的地方? – Petr

1
class myClass { 
    int x; 
    mutable int y; 
public: 
    myclass() : x(1) {} 
    void foo1() {x++; y++}  // this can change x or y 
    void foo2() const { y--; } // this can't change x by can change y 
}; 

如果您標誌着一個成員函數const這樣,你不能這樣做在該成員任何可能修改對象的成員(除非該成員是mutablestatic - 和static是不是真的一個對象的成員)。

請注意,這不會簡單地阻止您調用嘗試進行此類修改的函數 - 而是一個標記爲const但試圖修改對象狀態的函數根本無法編譯。

但是,我應該補充說,我完全不相信這是最好的設計。而是相反,它聽起來好像在x您的要求和y是非常複雜,他們可能會更有意義,因爲單獨的類是直接執行適當的限制(例如,通過提供operator=的重載只接受在正確的輸入情況)。

換句話說,使用mutable我上面顯示的是(我認爲)最簡單,最直接的問題的答案,你問過,但似乎相當有可能,你是不是真的問這個問題你應該,你就更有可能從改變設計中獲益 - 不幸的是,你還沒有告訴我們有足夠的瞭解了「大局」暗示什麼更好的設計可能。

+0

@MooingDuck:謝謝。更新。 –

+0

'mutable'?我想我會放棄'const'的想法,然後私下隱藏變量。或者單元測試什麼的。 –

+1

@MooingDuck:這是他問的最直接的答案。我想我應該添加一些警告。 –

1

好了,我不知道這是值得你的努力,無論如何,以防萬一這是測驗或某事物,嘗試私有繼承與朋友相結合:

class MyClassX { 
protected: 
    MyClassX() : x(1) {} 
    int x; 
public: 
    int getX() const { return x; } // read only access 
}; 
class MyClassY { 
protected: 
    MyClassY() : y(0) {} 
    int y; 
    friend class MyClass; 
public: 
    int getY() const { return y; } 
}; 
class MyClassXY : private MyClassX, private MyClassY { 
public: 
    void foo1() {x++; y++}  // this can change x or y 
}; 
MyClass : public MyClassXY { 
public: 
    void foo2() const { y--; } // this can't change x but can change y 
}; 
+0

不是測試,而只是我的好奇心。 – Petr

+0

@Petr - 我沒有嘗試我的解決方案,請告訴我是否需要修復。據我所知,它應該符合你的限制。 – PiotrNycz

+0

@Petr(+1)好奇心,我總是相信這是好事。 – PiotrNycz

0

從技術上講,答案是否定的,因爲長的類可以看到變量,它不是常量 - 它可以修改它。 但是,通過將要鎖定的變量解耦到單獨的類中,您可以完成所需的任務。

0

使用私有變量x創建一個類。在它寫你的方法。

從該類實際的類派生。使x持有人成爲實際課程的朋友。

X人利用CRTP像X架鑄件(靜態鑄造基地),把它變成一個指向您的實際類。

從暴露你的X支架的X吸氣。

我不會理會自己,但是這是不是濫用可變和const更好。

1

x一個subClassprivate成員,並作出foo1subClass的友元函數。像這樣:

class myClass { 
    int y; // Regular variable 
    myClass() : x (1) {} 
    void foo1() {x.x++; y++;} // This can change x 
    void foo2() {x.x--; y--;} // This shouldn't be able to change x 
          // I want it to throw a compile error 
    class subClass { 
     friend void myClass::foo1() ; // This must come after the declaration of foo1 
     int x ; // private 
    public: 
     subClass (int x) : x (x) { } 
     int read_x() const { return x ; } 
     } x ; 
}; 

這引發了一個編譯器錯誤,就在你想要的地方。

+0

我很困惑,因爲你從來沒有使用'read_x',但你是對的:http://ideone.com/JTkfSq –

+0

@Minging Duck:什麼是隻寫變量? – TonyK

相關問題