如何允许某些类的对象访问另一个类的对象的受保护成员

时间:2016-05-10 15:13:11

标签: c++ c++11 c++14 protected

我正在寻找以下问题的解决方案:

我有一个X课,其中(假设)只有protected个成员。我有几个类ABC,...

S

假设有一个类x成员的现有实例X(该实例可以是类X的实例,或任何合适容器的实例的子集/ derived-class / ...取决于类X):

  • 与(取决于)s相关的 S 类的任何实例x必须有权访问{ {1}} protected成员。
  • x protected成员的访问权限必须限制在x(和s)。
  • 实例x的创建和销毁必须保持实例s 活着不变

此外,在给定时间内,只存在一个x [关系]与s的实例。

换句话说,为了澄清上述要求:我需要任何实例x都可以访问类s的{​​{1}}成员,就像(例如)类的protected一样set S 是公开派生自X的,但继承中来自类X的成员子集必须保持 alive 不变是否创建或销毁实例X

此外,还必须满足以下要求:

  • s必须被视为不可复制且不可移动。
  • 由于维护成本的原因,一个涉及X protected X成员包装的解决方案虽然可以接受,但是不可取。
  • 制作S X个朋友的所有类别显然是不可接受的(对许多班级来说)。

当前实现的解决方案虽然不符合要求#5,但正在使用组合和父类来处理X S 朋友的类,例如:

class X
{
    // public: int get_prot();        // not allowed (rq#2)
    protected: int prot;
    friend class Xaxx;
    // friend A; friend B; ...        // not acceptable (rq#6)
};

class Xacc
{
protected:
    Xacc(X& x) : x(x) {}
    int& x_prot() { return x.prot; }  // not desirable (rq#5)
    X& x;
};

class A : public Xacc
{
public:
    A(X& x) : Xacc(x) {}
    void work()  { x_prot() = 1; }
};

测试的另一个有趣的解决方案,满足了#4期望的所有要求:

class A : public X
{
public:
    A(const X& x) : X(x) {}            // X not copyable (rq#4)
    void work()  { prot = 1; }
};

任何直到C ++ 14的解决方案都是可以接受的。谢谢你的帮助。

原理

澄清此问题的来源以及解决方案将以何种方式帮助我改进代码:

  • 集合 S 的每个类都代表状态机的状态(状态机在某种程度上受到了Gang of 4的状态模式的启发)。
  • 每个州必须有权访问一个共同的基础子对象(X的实例),它实现了所有类型的工作(算法,i / o等等)。
  • 当输入新状态时,会创建集合 S 中正确类的对象;退出状态时,对象被销毁,然后被新对象替换(新状态)。此开关中不得更改X的实例。

4 个答案:

答案 0 :(得分:2)

让外部类成为它需要访问的类的朋友吗?

http://www.cplusplus.com/doc/tutorial/inheritance/

答案 1 :(得分:2)

如果 S 中的课程具有简单的统一界面(例如单一工作方法),您可以通过制作更改当前实施以满足要求#5 Xacc是一个模板类,通过将对X的受保护部分的访问实现移动到Xacc的特化中。它看起来像这样:

class X 
{
protected:
    int prot;
    template<typename State> friend class Xacc;
};

template<class State>
class Xacc
{
public:
    Xacc(X &x) : x(x) {}
    void work();
private:
    X &x;
};

class S1;
template<> void Xacc<S1>::work()
{
    x.prot = 1;
};

class S1: public Xacc<S1>
{
public:
    S1(X &x): Xacc<S1>(x) {}
protected:
};

答案 2 :(得分:1)

也许您可以使用passkey模式的某种变体

class XKey {
    XKey(){}
    friend class Xacc;
};

class X {
public: 
    int& get_prot(XKey) { return prot; } // Only accessible to those who can construct XKey
protected:
    int prot;
};

class Xacc {
protected:
    Xacc(X& x) : x(x) {}
    X& x;    
    XKey getKey() { return XKey(); }    
};

class A : public Xacc {
public:
    A(X& x) : Xacc(x) {}
    void work()  { x.get_prot(getKey()) = 1; }
};

int main() {
    X x;
    A a(x);
    a.work();
    //x.get_prot(XKey()) = 2;  // Error: XKey::XKey() is private   
}

答案 3 :(得分:0)

我认为解决方案是:您必须为集合$scope.submit = function(usr, pw) { if(!usr || !pw) { alert('empty usr or pw'); return; } //your stuff, not mine $scope.list = []; var dataString = 'username='+ usr + '&password=' + pw; $scope.text = ''; var payload = { username: usr, password: pw }; $http.post('path/to/php/file', payload).then(function(response) { //success alert(response.data); }).catch(function(response) { //an error occurred alert(response.data); }); } 设置基类。

S可以是您的班级S,也可以是X

的分隔(新)班级

软件项目是需求和设计的平衡,当您列出所有6个需求时,解决方案仅限于您必须拥有具有共同功能的基类X:访问您的Xacc

你知道“空中楼阁”的故事吗?如何在没有1楼的情况下只有2楼?