根据上下文对类成员进行不同的访问

发布于 2024-12-08 12:29:45 字数 2100 浏览 2 评论 0原文

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

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

该类 Data 仅包含一个成员及其访问器,没有公共方法来操作该成员

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

我的目标是创建某种引用,保留指向数据的指针,并

  1. 在 MainApp 中
  2. 允许访问数据 时有两种行为禁止访问数据什么时候在前端中,

我列出了一些解决方案,例如 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
};

Let's say I have a class MainApp using methods of a dynamic library via an interface FrontEnd

FrontEnd uses internally instances of a class Data (contained in a class BackEnd)

This class Data only contains a member and its accessor, no public method to manipulate the member

Ok now MainApp has no knowledge of Data and can't access it but it needs indirectly to manipulate it

My goal is to create some kind of a reference keeping a pointer to Data with 2 behaviours

  1. forbidding access to Data when in MainApp
  2. Allowing access to Data when in FrontEnd

I listed some solutions like PIMPL idiom, Bridge or Adaptor pattern but the problem is I don't want to use the Reference like an interface but just like an holder

How can I handle it?

Here some code to illustrate:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

维持三分热 2024-12-15 12:29:45

考虑使用友谊 - 即使FrontEnd成为Referencefriend,这样您就可以在protected成员中< code>Reference 将允许您获取Data*。在 Reference.h 中,包含 FrontEnd.h(以允许友谊),在 FrontEnd.h 中,使用 Reference作为前向声明(即不包含标头)。仅在 FrontEnd 的实现文件中包含标头。您还必须将所有定义(在 FrontEnd.h 中)移至实现文件。

现在 MyApp 可以愉快地保存 Reference,但是Data* 只能通过 FrontEnd 获取。

Consider using friendship - i.e. make FrontEnd a friend of Reference, this way you can have a protected member in Reference which will allow you to get the Data*. In Reference.h, include FrontEnd.h (to allow friendship), in FrontEnd.h, use Reference as a forward declaration (i.e. don't include the header). Only include the header in the implementation file for FrontEnd. You'll have to move all the definitions (in FrontEnd.h to the implementation file as well.

Now MyApp can happily hold a Reference but Data* can only be got at by FrontEnd.

明天过后 2024-12-15 12:29:45

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

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 中。

If you want to allow external classes access to internals of another you can set it as a friend.

struct Foo;

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

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

This is a trade off obviously. It is alright to think about the two structs differently, but if they access each others internals they don't have much separation of concern. Use sparingly.

When you do this it is good practice to access the internals via method calls as opposed to manipulating them directly. It may seem like you are adding complexity and you are to some extent. It makes your access intentions clear, though.

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

You wouldn't want that count check littered throughout Foo, for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文