如何允许某些 classes 的对象访问另一个 classes 的对象的受保护成员
How to allow objects of some classes to access protected members of an object of another class
我正在寻找以下问题的解决方案:
我有一个 class X
,(假设)只有 protected
个成员。我有一组 S 几个 classes A
, B
, C
, ...
假设存在 class X
成员的现有实例 x
(该实例可能是 class X
的实例,或者任何合适的实例的子集 container/derived-class/... 取决于 class X
) :
- 集合S的class的任何实例
s
,与相关(取决于) x
,必须有权访问 x
. 的 protected
位成员
- 对
x
的 protected
成员的访问必须限制为 s
(和 x
)。
- 创建和销毁实例
s
必须保持实例 x
alive 和 unaltered.
此外,在给定时间,只有一个实例 s
[ 与 x
相关 ] 存在。
换句话说,为了阐明上述要求:我需要任何实例 s
都可以访问 class X
的 protected
成员,就像如果 (例如) S 的 classes 是从 X
公开派生的,除了来自 class [=13= 的成员子集] in inheritance 必须保持 alive 并且 unaltered 无论实例 s
是创建还是销毁。
此外,必须满足以下要求:
X
必须被认为是不可复制和不可移动的。
- 涉及
X
的 protected
成员的包装器的解决方案虽然可以接受,但由于维护成本而不可取。
- 让所有 class 组
S
成为 X
的朋友显然是不可接受的(对许多 classes)。
当前实施的解决方案虽然不满足要求 #5,但正在为 S 朋友的 class 部分使用组合和父 class X
个,例如:
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 中的每个 classes 代表状态机的状态(该状态机在某种程度上受到 Gang 的状态模式的启发共 4 个)。
- 每个状态都必须能够访问一个共同的底层子对象(
X
的实例),它实现了所有类型的工作(算法、i/o,等等...)
- 当进入一个新的状态时,在集合S中创建一个适当的class对象;当退出状态时,对象被销毁,然后由一个新对象(新状态)替换。不得在此开关中更改
X
的实例。
让外部 class 成为需要访问的 class 的朋友是不可能的吗?
我认为解决方案是:你的集合 S
必须有一个基础 class。
S
可以是您的 class X
或来自 X
的分离(新)class
软件项目是需求和设计的平衡,当您列出所有 6 个需求时,解决方案仅限于您必须有一个具有共同功能的基础 class Xacc
:访问您的 X
你知道故事"castles in the air"吗?我怎么只有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
}
如果您在 S 中的 classes 具有简单的统一接口(例如单个 'work' 方法),您可以更改当前的实现通过使 Xacc 成为模板 class 并将对 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:
};
我正在寻找以下问题的解决方案:
我有一个 class X
,(假设)只有 protected
个成员。我有一组 S 几个 classes A
, B
, C
, ...
假设存在 class X
成员的现有实例 x
(该实例可能是 class X
的实例,或者任何合适的实例的子集 container/derived-class/... 取决于 class X
) :
- 集合S的class的任何实例
s
,与相关(取决于)x
,必须有权访问x
. 的 - 对
x
的protected
成员的访问必须限制为s
(和x
)。 - 创建和销毁实例
s
必须保持实例x
alive 和 unaltered.
protected
位成员
此外,在给定时间,只有一个实例 s
[ 与 x
相关 ] 存在。
换句话说,为了阐明上述要求:我需要任何实例 s
都可以访问 class X
的 protected
成员,就像如果 (例如) S 的 classes 是从 X
公开派生的,除了来自 class [=13= 的成员子集] in inheritance 必须保持 alive 并且 unaltered 无论实例 s
是创建还是销毁。
此外,必须满足以下要求:
X
必须被认为是不可复制和不可移动的。- 涉及
X
的protected
成员的包装器的解决方案虽然可以接受,但由于维护成本而不可取。 - 让所有 class 组
S
成为X
的朋友显然是不可接受的(对许多 classes)。
当前实施的解决方案虽然不满足要求 #5,但正在为 S 朋友的 class 部分使用组合和父 class X
个,例如:
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 中的每个 classes 代表状态机的状态(该状态机在某种程度上受到 Gang 的状态模式的启发共 4 个)。
- 每个状态都必须能够访问一个共同的底层子对象(
X
的实例),它实现了所有类型的工作(算法、i/o,等等...) - 当进入一个新的状态时,在集合S中创建一个适当的class对象;当退出状态时,对象被销毁,然后由一个新对象(新状态)替换。不得在此开关中更改
X
的实例。
让外部 class 成为需要访问的 class 的朋友是不可能的吗?
我认为解决方案是:你的集合 S
必须有一个基础 class。
S
可以是您的 class X
或来自 X
软件项目是需求和设计的平衡,当您列出所有 6 个需求时,解决方案仅限于您必须有一个具有共同功能的基础 class Xacc
:访问您的 X
你知道故事"castles in the air"吗?我怎么只有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
}
如果您在 S 中的 classes 具有简单的统一接口(例如单个 'work' 方法),您可以更改当前的实现通过使 Xacc 成为模板 class 并将对 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:
};