如何限制对静态公共成员的访问?

时间:2016-04-26 10:41:59

标签: c++ class struct static-members

#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;
}

请参阅上面的代码和评论。除了使用accessors/mutators制作Settings::gs private之外,是否有其他方法可以限制对Settings::gs的访问权限,以便只能通过Settings个对象进行访问?就这样,任何函数都可以访问Settings::gs是否可以访问Settings对象。 Settings::gs本质上是一个全局对象。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

  

除了使Settings::gs private使用访问者/ mutator之外,还有其他方法可以限制Settings::gs的访问权限,以便只能通过Settings个对象访问吗?

不是真的(假设你想通过&#34来访问控件;#34;),这几乎就是private和访问者的意思。这是为实例和私有静态数据提供对内部(可能已检查)的访问。

您可以改变语法以获得所需的语义(指针,引用,const和非const),但最终一旦成员变量是公共的(或通过公共成员访问,例如指针或引用),您就会投降一定程度的控制。这里的控制是在函数中实现的,可以是成员函数或外部实用程序/辅助函数。

我不确定这里的意图。这取决于您通过&#34;。

访问的含义

如果仅仅是您所使用的语法,this answer (for the current question)提供了解决方案。

如果它更具控制力,您可以探索创建提供自定义operator*()operator->()的实用程序类的可行性,从而可以模拟&#34;一个智能指针(没有&#34;智能参考&#34;)。我不确定这会提供您所使用的语法。

您还可以探索pimpl模式/习语(opaque pointer),但它没有回答这个问题,但提供了一种替代设计,可以更好地解决您遇到的问题

答案 2 :(得分:-1)

但是,我可以想到几个选项,就像所有单例一样,这些都不是线程安全的:

  1. 您可以使用public reference来避免访问者/变更者:
  2. 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);
        }
    };
    
    1. 你实际上可以make it a full on singleton,虽然这需要一个访问者,但不是一个改变者,而且会花费你const
    2. 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);
          }
      };