Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何允许某些类的对象访问另一类对象的受保护成员_C++_C++11_C++14_Protected - Fatal编程技术网

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

C++ 如何允许某些类的对象访问另一类对象的受保护成员,c++,c++11,c++14,protected,C++,C++11,C++14,Protected,我正在寻找以下问题的解决方案: 我有一个类X,其中(假设)只有受保护的成员。我有一套S分为几类a,B,C 假设存在类x成员的现有实例x(该实例可能是类x的实例,或任何合适的容器/派生类/…的实例子集,具体取决于类x): 集合s的类的任何实例s,与x相关(取决于)必须能够访问受保护的成员x 对x受保护的成员的访问必须限于s(和x) 创建和销毁实例s必须保持实例x处于活动状态且未被更改 此外,在给定时间,只有一个与x相关的s[实例]存在 换句话说,为了澄清上述要求:我需要任何实例s都可以访问受保

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

我有一个类
X
,其中(假设)只有
受保护的
成员。我有一套S分为几类
a
B
C

假设存在类
x
成员的现有实例
x
(该实例可能是类
x
的实例,或任何合适的容器/派生类/…的实例子集,具体取决于类
x
):

  • 集合s的类的任何实例
    s
    ,与
    x
    相关(取决于)
    必须能够访问
    受保护的
    成员
    x
  • x
    受保护的
    成员的访问必须限于
    s
    (和
    x

  • 创建和销毁实例
    s
    必须保持实例
    x
    处于活动状态且未被更改
此外,在给定时间,只有一个与
x
相关的
s
[实例]存在

换句话说,为了澄清上述要求:我需要任何实例
s
都可以访问
受保护的
X
的成员,就像(例如)集合s的类是从
X
公开派生的一样,除了继承中来自类
X
的成员子集必须保持活动状态,并且无论创建还是销毁实例
s
,都必须保持不变

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

  • X
    必须视为不可复制和不可移动
  • 涉及
    X
    受保护的
    成员的包装的解决方案虽然可以接受,但由于维护成本的原因,并不可取
  • 显然,让set的所有类
    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的每个类都代表一个状态机的状态(该状态机在某种程度上是从四人帮的状态模式中得到启发的)
  • 每个状态都必须有权访问一个公共的底层子对象(
    X
    )的实例,该子对象实现所有种类的工作(算法、i/o等…)
  • 当进入新状态时,将创建集合S中适当类别的对象;当状态退出时,对象将被销毁,然后被新状态(新状态)替换。不能在此开关中更改
    X
    的实例

是否让外部类成为它需要访问的类的朋友是不可能的


我认为解决方案是:必须为集合
S
创建一个基类

S
可以是您的类
X
或与
X

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


你知道“空中城堡”这个故事吗?我怎么可能只有二楼而没有一楼呢?

也许你可以使用一些不同的模式


如果S中的类有一个简单的统一接口(例如,一个“工作”方法),您可以通过将Xacc设置为模板类并将对X的受保护部分的访问的实现移动到Xacc的专门化中来更改当前实现以满足需求#5。它看起来是这样的:

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:
};
X类
{
受保护的:
int-prot;
模板朋友类Xacc;
};
模板
Xacc类
{
公众:
Xacc(X&X):X(X){}
无效工作();
私人:
X&X;
};
S1类;
模板void Xacc::work()
{
x、 prot=1;
};
S1类:公共Xacc
{
公众:
S1(X&X):Xacc(X){}
受保护的:
};

这也许应该是一个评论,因为你要求澄清。@JonHarper:我认为这是一个反问句,因此是一个答案。也是正确的。OP显然是在做一个练习,只需要一个指针。@Loki:不是一个练习,一个真正的问题,我必须在一个真正的程序中解决;谢谢你的链接,但我正在寻找一种模式,我想我知道友谊是如何运作的。@shrike:朋友就是答案。你只是还没看透而已。你不想交很多课的朋友。但是只要满足一定的条件,您仍然可以通过结交一个类朋友来访问
s
中的所有类。基本上,您有三种合法的方式访问受保护的成员。1) 继承权。2) 获取指向会员友谊的指针。您已经排除了只剩下3个的1和2。@shrike:如果这是一个真实的代码,请告诉我们真实的细节,而不是编造不完整的类名,并像假设的那样措辞。给我们真正问题的代码。用编程语言来表达程序,英语是一种糟糕的语言。它将比英语更简洁、更有意义,而且歧义更少。这是XY问题的定义。你到底想做什么?还是仅仅是“把作业交给某人”的时间lol@Lightness当前位置这个问题看起来像家庭作业吗?该死!但是我离开学校20多年了。。。我想做的是解决这个问题,我尽了最大的努力
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:
};