根据上下文对类成员的访问权限不同

时间:2011-10-04 14:20:23

标签: c++ design-patterns reference friend access-control

假设我有一个类MainApp使用动态库的方法通过接口FrontEnd

FrontEnd使用类Data的内部实例(包含在BackEnd类中)

此类Data仅包含成员及其访问者,没有公共方法来操作成员

好了,现在MainApp不了解数据,也无法访问数据,但需要间接操作它

我的目标是创建某种引用,保持指向具有2个行为的数据的指针

  1. 禁止在MainApp中访问数据
  2. 允许在FrontEnd中访问数据
  3. 我列出了一些解决方案,如PIMPL习惯用法,桥接器或适配器模式,但问题是我不想像参考界面那样使用参考,但就像持有者一样

    我该如何处理?

    这里有一些代码来说明:

    Data.hpp

    struct Data {
        Data(int i):member(i){}
        int getMember();
    private :
        int member;
    };
    

    BackEnd.hpp

    #include "Data.hpp"
    
    struct BackEnd {
        BackEnd(){}
        Data* createData(int i) {
          Data* d = new Data(i);
          mDatas.push_back(d);
          return d;
        }
    
        void doSomething(Data* d, int param) {
          int r = param+d->getMember();
          /*do other things with d*/
        }
    private:
        vector<Data*> mDatas;
    };
    

    Reference.hpp

    #include //???
    
    struct Reference {
        Reference(Data* d):mData(d){}
    private:
        //no access to data->member
        Data* mData;
    };
    

    FrontEnd.hpp

    #include "Data.hpp"
    #include "Reference.hpp"
    #include "BackEnd.hpp"
    
    struct FrontEnd {
        Reference* createData(int i) {
          Data* d = mBackEnd->createData(i);
          //conversion Data to Reference
          Reference ref = new Reference(d);
          return ref;
        }
    
        void doSomething(Reference* ref) {
          //In the Front-End, I want an access to Ref->mData
          Data* d = ref->getData();//Allows access to Ref->mData
          int result = mBackEnd->doSomething(d);
        }
    private:
        BackEnd* mBackEnd;
    };
    

    MainApp.hpp

    //I don't want to reference Data.hpp
    #include "Reference.hpp"
    #include "FrontEnd.hpp"
    
    struct MainApp {
        Reference* createRef(){ mRef = mFrontEnd->createData(8);}
        void doSomething(){ mFrontEnd->doSomething(mRef); }
    private:
        FrontEnd* mFrontEnd;
        Reference* mRef;
        //I want to keep a reference to Data without using Data directly
        //Forbids access to mRef->mData
    };
    

2 个答案:

答案 0 :(得分:2)

如果您想允许外部类访问另一个内部的内部,您可以将其设置为friend

struct Foo;

struct Bar {
private:
  friend struct Foo;
  int count;
};

struct Foo {
  void doBarStuff(Bar &bar) {
    bar.count = 2;
  }
};

这显然是一种折衷。可以不同地考虑这两种结构,但如果它们相互接触,则它们没有太多关注点。谨慎使用。

执行此操作时,最好通过方法调用访问内部,而不是直接操作它们。看起来你似乎在增加复杂性,而且你在某种程度上也是如此。但是,它会使您的访问意图变得清晰。

struct Foo;

struct Bar {
private:
  friend struct Foo;
  void setCount(int c) {
    if (count < 0)
      throw std::logic_error("out of range");
    count = c;
  }
  int count;
};

struct Foo {
  void doBarStuff(Bar &bar) {
    bar.setCount(2);
  }
};

例如,您不希望在Foo中遍布计数检查。

答案 1 :(得分:2)

考虑使用友情 - 即FrontEnd friend Reference protected,这样您就可以在Reference中拥有Data*成员,这样您就可以得到Reference.h。在FrontEnd.h中,包含FrontEnd.h(以允许友谊),在Reference中,使用FrontEnd作为前向声明(即不包括标题)。仅在FrontEnd.h的实现文件中包含标头。您必须将所有定义(在MyApp中)移动到实现文件中。

现在Reference可以很高兴地拥有Data*FrontEnd只能通过{{1}}获得。