【问题标题】:C++ sharing object between two classC ++在两个类之间共享对象
【发布时间】:2018-02-27 17:31:49
【问题描述】:


假设我有两个班级:FirstContainerSecondContainer
它们对ThirdContainer 类拥有相同的引用(传入它们的构造函数)。
FirstContainer 和 SecondContainer 有以下方法:
- addMemberToThirdContainer
- delMemberOfThirdContainer
- getThirdContainerMembers

修改 ThirdContainer 后,我希望另外两个使用 getThirdContainerMembers() 进行更新。为此,我使用了观察者/监听者模式

ThirdContainer 有一个监听器列表和一个方法:addNewListenerFirstContainerSecondContainer 注册:mThirdContainer.addNewListener(this);

我不确定这是不是这样做的好方法,我是面向对象的新手。
我还有什么其他可能实现这样的目标?
我不执着于我所说的任何东西,它只是在这里,因为我很难解释我想做什么。我希望这很清楚。 感谢您的帮助,
最好的,

编辑: 使用前向声明怎么样?我可以这样做:

 class ParentContainer {
 public:
     ParentContainer(ThirdContainer&)
     : mFirstContainer(*this), mSecondContainer(*this) { };

     ~ParentContainer(); 

     void addMemberToThirdContainer() {
        mThirdContainer.addMember();
        notify();
     }; 

     void delMemberOfThirdContainer() {
        mThirdContainer.delMember();
        notify();
     };

 private:
     std::vec<int>& getMemberOfThirdContainer() {
        return mThirdContainer.getMember();
     };

     void notify() {
        auto vec = getMemberOfThirdContainer();
        mFirstContainer.update(vec);
        mSecondContainer.update(vec);
     };

     ThirdContainer& mThirdContainer;
     FirstContainer  mFirstContainer;
     SecondContainer mSecondContainer; 
 };

然后在 FirstContainer 和 SecondContainer 中类似:

 class ParentContainer;

 class FirstContainer {
 public:
      FirstContainer(ParentContainer&);
      ~FirstContainer(); 

      void update(std::vector<int>& vec);

 private:
      ParentContainer& mParentContainer;
 };

在 FirstContainer 和 SecondContainer 中,我可以通过以下方式访问 ThirdContainer:
mParentContainer.addMemberToThirdContainer 和 mParentContainer.DelMemberOfThirdContainer。
我会收到通知。我的意思是我猜....

【问题讨论】:

  • 这两个对象是否共享第三个对象的所有权?还是他们需要一个非拥有的指针或对第三个对象的引用?
  • 首先,一个简短的语言挑剔:一个类描述了这个类的实例的样子。类和其他类型(指针、整数等)的实例是对象。这只是为了弄清楚含义,因为“在两个类之间共享对象”有点不清楚。现在,关于您的问题,无法判断您所描述的是否聪明,因为信息太少了。我建议你从你想要达到的目标开始,而不是从可能有缺陷的方法开始。
  • FirstContainer 和 SecondContainer 不应拥有对 ThirdContainer 的所有权。 ThirdContainer 是一种模型,即使没有其他两个它也应该存在(相反是错误的)。感谢您的帮助
  • 嘿 ulrich,我想要的是让两个类与第三类的同一个实例进行通信。并且每当在共享实例中进行更改时,都会通知共享它的类。将来,这两个类可能会共享多个第三类的实例。

标签: c++ c++11 observer-pattern constructor-injection


【解决方案1】:

如果您喜欢使用库,您可以使用任何提供 Signal/Slot 系统的库,例如 Boost 或 Qt。

如果你不喜欢图书馆,你应该尝试

  1. 创建一个接口(在 C++ 中,只是一个带有纯虚方法的抽象类,onModified 例如:

    class ThirdContainerListener {
        public: virtual void onContainerModified() = 0;
        // Virtual: is to make it overridable
        //  = 0: is the C++ way to say "abstract", 
        //         which means this function MUST be overridden.
    };
    
  2. 创建一个指向侦听器的vector 指针(为安全起见,请尝试使用智能指针,例如shared_ptr){这在 ThirdContainer 内}

    vector<shared_ptr<ThirdContainerListener>> listeners;
    
  3. Make(也在ThirdContainer内部),一个添加监听器的函数,像这样

    void addNewListener(shared_ptr<ThirdContainerListener> container) {
        listeners.push_back(container); // Adds the pointer to the listeners
    }
    
  4. 像这样隐藏你的真实容器

    private: vector<int> list;
    
  5. 创建一个调用所有监听器的私有函数,在本地使用

    private: void callAllListeners() {
        // Traverse through all the listeners
        for(shared_ptr<ThirdContainerListener> listener: listeners) {
            // Call each one's overridden function
            listener->onContainerModified();
        }
    }
    
  6. 公开修改容器的函数,调用所有侦听器,就像那样

    public: void addData(int d) {
                list.push_back(d);
                callAllListeners();
            }
    
    // Also you could make "removeDataByIndex", "addManyData", etc...
    
  7. 在 First 和 Second 容器中使用 shared_ptr&lt;ThirdContainer&gt;,以确保您的类不会泄漏内存或指向任何内容(悬空指针)

【讨论】:

  • 您好,谢谢您的回答。这就是我现在正在做的事情,有没有办法在没有广播者/听众模式的情况下实现同样的事情?
  • 如果您只想更新其他两个容器,只需使用最后一部分,即在 both 容器中使用 shared_ptr&lt;ThirdContainer&gt;。这使得任何更改发生在一个,另一个发生,因为shared_ptr 只是一个指针,这意味着两者指向同一个对象。但是如果你想让其他人听到这个变化,我认为除了使用广播器/侦听器之外没有其他方法
  • 问题是我有很多 ThirdContainer 的实例,我只想听一个(选定的)。我不希望我的所有 ThirdContainer 都保存指向侦听器的指针向量。有什么办法可以管理吗?
  • 如果我理解正确的话,你可以把vector写成shared_ptr&lt;vector&lt;ThirdContainerListener&gt;&gt;,这样听众就可以共享了(但我不认为这是个好主意)
  • 是的,我有多个 ThirdContainer 同时存在的实例,并且只有一个 FirstContainer 和 SecondContainer。 When a ThirdContainer instance is Selected I want the FirstContainer and the SecondContainer to listen to it.我想避免在我的所有 ThirdContainer 实例上都有侦听器向量,仅在选定的一个实例上。
【解决方案2】:

ThirdContainer被修改时,我希望另外两个使用getThirdContainerMembers()更新。

为什么?这对我来说真的没有多大意义。或者至少 - 我不明白你的动机。为什么这两个容器不能在他们真正需要的时候获取成员,而不是每次更新一次?或者更好 - 为什么要获取成员的副本,当您可以将成员保留在 ThirdContainer 中并在其中迭代它们?

现在,您可以说“可能迭代器在此类访问期间失效”。但这也是打电话给getThirdContainerMembers()时的一个问题。

ThirdContainer 有一个监听器列表和一个方法:addNewListener。

我不喜欢这种方法,建议您考虑是否真的要遵循它。

我相信它更适合具有动态类型对象的解释语言,您可以在其中动态添加或删除功能,或者至少它们具有解释器/虚拟机提供的观察和自省机制。使用此类语言,您的ThirdContainer 不必提前设计以支持侦听器。

但是,使用 C++,您将不得不强加于 ThirdContainer 的封装设计(或至少 - 从现有设计继承),以便它支持侦听器)。但是,另外一次您需要监听其他事件,并且您将再次需要子类化或更改 ThirdContainer 的接口 - 不,我宁愿不这样做。

相反,考虑让向ThirdContainer 添加元素的人同时负责更新共享它的FirstContainerSecondContainer 实例;或完全避免更新。

【讨论】:

  • 您好,感谢您的回答。这三个容器在音频插件中形成了 MVC 模式。在 GUI 中有两个主要部分,在我的问题中由 FirstContainer 和 SecondContainer 表示。这两个类都嵌入了控制器和视图功能。它们持有对模型(ThirdContainer)的引用以进行交互。用户可以单击这两个部分将成员添加到模型中。当向模型添加新成员时,FirstContainer 和 SecondContainer 必须将子项(gui 的新部分)添加到它们的向量中,并将对模型新成员的引用传递给它们以进行交互。
  • “相反,考虑让向 ThirdContainer 添加元素的人同时负责更新共享它的 FirstContainer 和 SecondContainer 实例;或者完全避免更新”这类似于我回答的编辑部分吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
  • 2013-05-26
  • 2010-10-22
  • 1970-01-01
  • 2011-04-20
相关资源
最近更新 更多