简体   繁体   English

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

[英]How to allow objects of some classes to access protected members of an object of another class

I am looking for a solution to the following problem: 我正在寻找以下问题的解决方案:

I have a class X with (assuming) only protected members. 我有一个X类,(仅假设) protected成员。 And I have a set S of several classes A , B , C , ... 我有几个班的集合S ABC ,...

Assuming there is an existing instance x of class X members (which instance may be, either an instance of class X , or a subset of an instance of any suitable container/derived-class/... depending on class X ) : 假设有一个现有实例x类的X成员(其实例可以是任一类的一个实例X ,或任何合适的容器/派生类的一个实例的一个子集/ ...取决于类X ):

  • Any instance s of a class of the set S , in relation with (depending on) x , must have access to protected members of x . x 有关 (取决于x )的集合S类的任何实例s都必须有权访问x protected成员。
  • Access to protected members of x must be restricted to s (and x ). x protected成员的访问必须限于s (和x )。
  • Creation and destruction of instance s must keep instance x alive and unaltered . 实例s创建和销毁必须使实例x保持生存不变

Additionally, at a given time, only one instance s [ in relation ] with x is existing. 另外,在给定的时间,仅存在一个与x 有关的实例s [。

In other words and to clarify the above requirements: I need that any instance s have access to protected members of class X , just like if (for example) classes of the set S were publicly derived from X , except that the subset of members coming from class X in inheritance must remain alive and unaltered whether instance s is created or destroyed. 换句话说,并澄清了上述要求:我需要的任何实例s访问protected类的成员X ,就像如果(例如)集合S被公开源自类X ,除了成员的子集来从类X在继承必须保持活着 ,并没有改变实例是否s创建或破坏。

In addition, the following requirements must be met: 另外,必须满足以下要求:

  • X must be considered non-copyable and non-movable. X必须被视为不可复制且不可移动。
  • A solution involving wrapper to protected members of X , though acceptable, is not desirable due to maintenance cost. 尽管可以接受,但涉及包装X protected成员的解决方案由于维护成本而并不理想。
  • Making all classes of set S friends of X is obviously not acceptable (to many classes). X的集合S所有类作为X朋友显然是不可接受的(对于许多类而言)。

The currently implemented solution, that though does not fulfills requirement #5, is using composition and a parent class for classes of S friend of X , eg: 当前实现的解决方案虽然不满足要求#5,但正在为XS朋友的类使用组合和父类,例如:

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

Another interesting solution tested, that fulfills all requirements expect #4 though: 经过测试的另一个有趣的解决方案,可以满足所有要求,但是期望#4:

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

Any solution up to C++14 is acceptable. 最高可以支持C ++ 14的任何解决方案。 Thanks for your help. 谢谢你的帮助。


Rationale : 理由

To clarify where this problem comes from and in which way a solution will help me improve my code: 为了弄清楚这个问题的根源和解决方法,将有助于我改善代码:

  • Every classes of the set S represent states of a state-machine (which state-machine is in some way inspired from the State pattern from the Gang of 4). 集合S的每个类都表示状态机的状态(该状态机在某种程度上受到4位群的状态模式的启发)。
  • Each state must have access to a common underlying sub-object (the instance of X ) which implements all sort of works (algorithms, i/o, and so on...) 每个状态都必须访问一个公共的基础子对象( X的实例),该子对象可以实现各种工作(算法,I / O等)。
  • When a new state is entered, an object of the proper class in set S is created; 当进入新状态时,将创建集合S中适当类别的对象; when the state is exited, the object is destroyed, then replaced by a new one (a new state). 退出状态后,对象将被销毁,然后由新对象(新状态)替换。 The instance of X must not be altered in this switch. X的实例不得在此开关中更改。

Is making the external class a friend of the class it needs access to out of the question? 是否使外部类成为了它所无法访问的类的朋友?

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

If your classes in S have a uniform interface that is simple (eg a single 'work' method), you can change your current implementation to fulfill requirement #5 by making Xacc a template class and by moving the implementation of the access to the protected parts of X into the specializations of Xacc. 如果您在S中的类具有简单的统一接口(例如,单个“工作”方法),则可以通过将Xacc设置为模板类并将访问权限的实现移至受保护对象来更改当前实现,以满足要求#5。 X的一部分变成Xacc的专业化。 It would look like this: 它看起来像这样:

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

Perhaps you could use some variant of the passkey pattern 也许您可以使用密码模式的一些变体

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   
}

I think the solution is: you have to have a base class for your set S . 我认为解决方案是:必须为集合S提供一个基类。

S can be your class X or a separated (new) class from X S可以是你的类X或从分开的(新)类X

software project is balance of requirement and design, when you listed all 6 requirements, the solution is limited to you have to have a base class Xacc which has common functionality: access your X 软件项目是需求与设计之间的平衡,当您列出所有6个需求时,解决方案仅限于您必须拥有具有通用功能的基类Xacc :访问X

do you know story "castles in the air"? 你知道故事“空中的城堡”吗? how do I only have 2nd floor without 1st floor? 我如何只有2楼而没有1楼?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM