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