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

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

本文关键字:对象 另一个 受保护 成员 访问 何允许      更新时间:2023-10-16

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

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

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

  • 集合S的类的任何实例s相关(取决于)x,必须访问xprotected成员
  • xprotected成员的访问必须限制为s(和x
  • 创建和销毁实例s必须保持实例x处于活动状态未更改

此外,在给定时间,仅存在一个具有x的实例s[relationship]。

换句话说,为了澄清上述要求:我需要任何实例s都可以访问类Xprotected成员,就像(例如)集合S的类是从X公开派生的一样,除了继承中来自类CCD_ 26的成员的子集必须保持活动并且无论实例CCD_。

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

  • X必须被视为不可复制且不可移动
  • 涉及Xprotected成员的包装器的解决方案虽然是可接受的,但由于维护成本的原因是不可取的
  • 使集合S的所有类成为X的朋友显然是不可接受的(对于许多类来说)

目前实现的解决方案虽然不能满足第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; }
};

测试了另一个有趣的解决方案,它满足了预期的所有要求#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中的类有一个简单的统一接口(例如一个"work"方法),您可以通过将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:
};

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

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

也许您可以使用密钥模式的一些变体

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有一个基类。

S可以是您的类别X,也可以是与X 分离的(新)类别

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

你知道"空中楼阁"这个故事吗?我怎么只有二楼而没有一楼?

相关文章: