2016-04-26 24 views
-1
#include <cstdio> 

struct Settings 
{ 
    int i1, i2; 
    Settings(int i1, int i2) : i1(i1), i2(i2) {} 

    struct GeneralSettings 
    { 
    int gi1, gi2; 
    } static gs; 

    void do_something() const 
    { 
    printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2); 
    } 
}; 

Settings::GeneralSettings Settings::gs; 

int main() 
{ 
    Settings s1(0,1); 
    Settings s2(1,0); 

    s1.gs.gi1 = 1;   // I would like to access GeneralSettings like this only! 
    Settings::gs.gi2 = 1; // Can i prevent global access like this? 

    s2.do_something(); 

    return 0; 
} 

請參閱上面的代碼和評論。除了使用Settings::gsprivateaccessors/mutators之外,還有其他方法可以限制對Settings::gs的訪問,因此只能通過Settings對象訪問它嗎?它的方式是,任何函數都可以訪問Settings::gs,無論它是否有權訪問Settings對象。 Settings::gs實質上是一個全局對象。如何限制對靜態公衆成員的訪問?

+2

什麼是這樣做的呢? – Holt

+0

@Holt:避免將Settings :: GeneralSettings暴露給每個函數。 –

+0

你已經在Settings結構中顯示了一切,你爲什麼只關心靜態成員? – zoska

回答

3

我還沒有得到這樣的點,但你可以使用一個公開提及一個私有的靜態成員(我不會建議這樣做的方式):

struct A { 
private: 
    struct B { int x, y; } static _b; 

public: 
    // c++11 initialization, prior you need to initialize b in the 
    // constructor of A 
    B &b{_b}; 
}; 

A::B A::_b{0, 0}; 

然後:

int main() { 
    A a1, a2; 

    std::cout << a2.b.x << " "; 
    a1.b.x = 4; 
    std::cout << a2.b.x << std::endl; 
} 

輸出:

0 4 

正如評論所指出的@Niall,具有參考作爲屬性會刪除默認的賦值運算符:

A a1, a2; 
a2 = a1; // copy assignment is implicitly deleted 

但是如果你需要它,你總是可以創建自己的,因爲你並不需要更新b

struct A { 
private: 
    struct B { int x, y; } static _b; 
public: 
    B &b{_b}; 
    A& operator= (A const&) { 
     // ok, no need to update this->b! 
     return *this; 
    } 
}; 

A a1, a2; 
a1 = a2; // ok 
+0

有趣的選擇。 'B&b {_b};'有效地使'A'不可分配(賦值運算符被隱式刪除)。你可以使它成爲一個指針'B * b {b} {b},但是它反過來又會受到它可以被設置爲'nullptr'(但至少限於當前對象實例)的缺點。包裝可以被寫/用於限制或允許公共成員('b')所需的語義(例如'std :: reference_wrapper',但最終控制仍然通過某種類型的函數來執行(例如'reference_wrapper :: get ()')。 – Niall

+0

@Niall'B&b {_b}'刪除默認的賦值操作符,但它不會阻止你創建自己的,如果你需要它(因爲你不需要賦值給'b'這種情況應該沒問題) – Holt

+0

這是事實,也許爲了清楚起見,在答案中加上了這個。 – Niall

1

除了使Settings::gsprivate與存取/存取器,是否有其他方法來限制訪問Settings::gs,以便它只能通過Settings對象訪問?

不是真的(假設你想要通過「access through」訪問時的控件),這幾乎就是private和訪問器的意義所在;即爲實例和私有靜態數據提供對內部的訪問(可能被檢查)。

你可以改變語法來獲得所需的語義(指針,引用,常量和非常量),但最終一旦成員變量是公共的(或通過公共成員訪問,如指針或引用),你放棄一定的控制權。這裏的控制是在函數中實現的,是一個成員函數或一個外部實用程序/幫助函數。

我不確定這裏的意圖。這取決於您「通過訪問」的含義。

如果它只是你之後的語法,this answer (for the current question)提供了一個解決方案。

如果是更多的控制,您可以探索創建實用類的可行性,該類提供自定義operator*()operator->(),因此您可以「模仿」智能指針(在沒有「智能參考」的情況下)。我不確定這會提供你之後的語法。

你也可以探索pimpl模式/成語(opaque pointer),它不回答問題,但提出了一個可以更好地解決您的問題的替代設計。

-1

我能想到幾個選項,不過,像所有的單身人士,這些不會是線程安全的:

  1. 你可以只使用一個public reference避免存取/存取器:
struct Settings { 
private: 
    struct GeneralSettings { 
     int gi1, gi2; 
    } static _gs; 
public: 
    int i1, i2; 
    GeneralSettings& gs; 
    Settings(int i1, int i2) : i1(i1), i2(i2), gs(_gs) {} 

    void do_something() const { 
     printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2); 
    } 
}; 
  • 你實際上可以make it a full on singleton,儘管這將需要訪問,雖然不是突變,它會花費你您const
  • struct Settings { 
        struct GeneralSettings { 
         int gi1, gi2; 
        }; 
    
        GeneralSettings& gs() { 
         static GeneralSettings gs; 
    
         return gs; 
        } 
    
        int i1, i2; 
        Settings(int i1, int i2) : i1(i1), i2(i2) {} 
    
        void do_something() { 
         printf("%d %d %d %d\n", i1, i2, gs().gi1, gs().gi2); 
        } 
    }; 
    
    +0

    @Downvoter請解釋嗎?我認爲這是一個很好的答案 –