在C ++中有没有办法创建“超私有”变量?

时间:2011-09-28 11:40:17

标签: c++ oop

我对C ++的功能有一个想法,我想知道是否可以创建。

假设我希望'MyClass'中的私有变量只能由两个函数访问,即公共getter和setter。也就是说,如果MyClass的另一个公共或私有函数试图获取或更改我的超私有变量的值,我将得到编译错误。但是,getter和setter表现正常。

有什么想法吗?

编辑1:用例是让getter / setter执行错误检查或其他形式的逻辑。我甚至不希望班级本身直接接触变量。

编辑2: 那样的话呢:

template <class T>
class State{
private:
    T state;

public:
    State()
    {
        state = 0;
    }

    T getState()
    {
        return state;
    }

    void setState(T state)
    {
        this->state = state;
    }
};

然后任何类都可以继承它并仅通过getter / setter访问'state'。当然,如果没有根据你想要的逻辑修改getter和setter,这个类就没用了。

4 个答案:

答案 0 :(得分:62)

C ++中的可访问性粒度就是这个类。

因此,如果您只需要为两个方法提供变量,则需要将变量和两个方法移动到一个单独的类中,专门用于保护隐私。

答案 1 :(得分:30)

您可以将变量包装在一个类中,并将其设置为私有,并使用const T& getter。比你声明包含类的get和set成员函数作为该包装器的朋友。现在,您将包装类保留为原始类中的成员。这应该达到你想要的效果,虽然它看起来很难维护而且不是很有用。

所以这里有一些虚拟实现,展示了它是如何工作的(注意整个new VeryPrivateWrapper业务只是一种古怪的声明方式,unique_ptr会更有帮助):

class VeryPrivateWrapper;

class Original {
  VeryPrivateWrapper* m_wrapper;

public:
  Original();
  // imagine that I remembered the rule of three here
  void set(int);
  void other();
};

// make this a template for more fun
class VeryPrivateWrapper {
  int m;
public:
  const int& get() const { return m; } 
  // !!!
  // the important bit 
  // !!!
  friend void Original::set(int);
};

Original::Original() : m_wrapper(new VeryPrivateWrapper) {}

void Original::set(int i) {
    m_wrapper->m = i;
}

void Original::other() {
  // this borks as we would like
  // m_wrapper->m = 23;
}

int main()
{
  Original o;
  o.set(3);
  return 0;
}

答案 2 :(得分:10)

我相信这就是你要求的。这是可取的吗?有些人会认为这是令人厌恶的。

如果您决定使用它,您可能希望从宏中提取公共Get和Set并手动编写。

#define SUPER_PRIVATE(c,t,m) \
template <typename C, typename T> \
class SuperPrivate##m { \
    friend T& C::Get##m(); \
    friend void C::Set##m(const T&); \
    T value; \
}; \
public: \
    t& Get##m() { return m.value; } \
    void Set##m(const t& value) { m.value = value; } \
private: \
    SuperPrivate##m<c,t> m; 

class SomeClass
{
public:
    SomeClass()
    {
        SetX(42);
        SetY(58);
    }
    int DosomethingWithX() { return GetX() * 2; }
//  int DosomethingWithX2() { return X.value * 2; } // error
//  int DosomethingWithX3() { return X; } // error

    SUPER_PRIVATE(SomeClass, int, X);
    SUPER_PRIVATE(SomeClass, int, Y);
};

int main()
{
    SomeClass someObject;
    int x1 = someObject.GetX();
    int y1 = someObject.GetY();
    someObject.SetY(89);
    int y2 = someObject.GetY();
    int x2 = someObject.DosomethingWithX();

}

答案 3 :(得分:5)

我会给变量添加一个非常丑陋的名称,并为getter / setter添加一个很好的名称:

class Foo
{
private:
    int _hey_do_not_use_me_im_super_private_whatever;
public:
    int get_whatever() const
    {
        //extra logic
        return _hey_do_not_use_me_im_super_private_whatever;
    }
    void set_whatever(int we)
    {
        //extra logic
        _hey_do_not_use_me_im_super_private_whatever = we;
    }
};

评论表明继承您的代码的人会非常欢迎超级私人的意思。