2016-04-26 22 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请解释吗?我认为这是一个很好的答案 –