【问题标题】:Accessing Members of Containing Objects from Contained Objects从包含对象访问包含对象的成员
【发布时间】:2015-09-28 20:06:52
【问题描述】:

如果我有多个级别的对象包含(一个对象定义并实例化另一个定义并实例化另一个对象的对象..),是否有可能访问上层,包含 -对象变量和函数好吗?

例子:

    class CObjectOne
    {
    public:
       CObjectOne::CObjectOne() { Create(); };

       void Create();

       std::vector<ObjectTwo>vObejctsTwo;
       int nVariableOne;
    }
    bool CObjectOne::Create()
    {
       CObjectTwo ObjectTwo(this);
       vObjectsTwo.push_back(ObjectTwo);
    }

    class CObjectTwo
    {
     public:
       CObjectTwo::CObjectTwo(CObjectOne* pObject)
       {
        pObjectOne = pObject;
        Create();
       };

       void Create();
       CObjectOne* GetObjectOne(){return pObjectOne;};

       std::vector<CObjectTrhee>vObjectsTrhee;
       CObjectOne* pObjectOne;
       int nVariableTwo;
    }
    bool CObjectTwo::Create()
    {
       CObjectThree ObjectThree(this);
       vObjectsThree.push_back(ObjectThree);
    }

    class CObjectThree
    {
     public:
       CObjectThree::CObjectThree(CObjectTwo* pObject)
       {
        pObjectTwo = pObject;
        Create();
       };

       void Create();
       CObjectTwo* GetObjectTwo(){return pObjectTwo;};

       std::vector<CObjectsFour>vObjectsFour;
       CObjectTwo* pObjectTwo;
       int nVariableThree;
    }
    bool CObjectThree::Create()
    {
       CObjectFour ObjectFour(this);
       vObjectsFour.push_back(ObjectFour);
    }

main()
{
    CObjectOne myObject1;
}

说,我需要从 CObjectThree 中访问 CObjectOne 中的 nVariableOne。我想这样做:

int nValue = vObjectThree[index].GetObjectTwo()->GetObjectOne()->nVariable1;

但是,在编译并运行我的应用程序后,我收到内存访问冲突错误。

  • 上面的代码有什么问题(它是示例,可能包含拼写错误)?
  • 我是否必须动态而不是静态创建对象?
  • 有没有其他方法可以通过包含对象来实现存储在包含对象中的变量?

【问题讨论】:

  • 您的代码不正确。你所有类的所有成员都是私有的,所以这永远不会编译。此外,您的类定义必须以分号结尾。请发布重现错误的正确、有效的代码。
  • @Space_C0wb0Y:您好,感谢您的评论。我想发布我的原始代码,但是,我将它分布在几个类文件中。为了显示我的代码,我必须添加大量文本。如果通过 this 引用包含对象应该有效,即使对象是静态创建的,我基本上对原理感兴趣。
  • 如果您想要一个好的答案,您将不得不在问题中投入一些工作。这可能包括编写一个实际编译和重现错误的小型示例应用程序。如果不查看导致错误的实际代码,就很难找到错误的原因。

标签: c++ oop visual-c++ containment


【解决方案1】:

当你传递一个指向容器对象的指针时,这个指针有时被称为后向指针。我看到这种技术一直在 GUI 库中使用,其中小部件可能想要访问其父小部件。

话虽如此,你应该问问自己是否有更好的设计不涉及循环依赖(循环是指容器依赖于容器,容器依赖于容器) .

您不必严格动态地创建对象以使反向指针技术起作用。您始终可以获取堆栈分配(或静态分配)对象的地址。 只要该对象的生命周期仍然存在,而其他人正在使用指向它的指针。但实际上,这种技术通常用于动态创建的对象。

请注意,您也可以使用反向引用而不是反向指针。


我想我知道是什么导致了您的分段错误。当您的向量重新分配它们的内存时(由于增长到更大的大小),旧向量元素的地址变得无效。但是这些对象的子(和孙)仍然在它们的反向指针中保存旧地址!

要使后向指针起作用,您必须动态分配每个对象并将它们的指针存储在向量中。这将使内存管理更加混乱,因此您可能需要使用智能指针或 boost::ptr_containers。


在看到您在另一个答案中发表的评论后,我现在对您要完成的工作有了更好的了解。您应该研究通用树结构和复合模式。复合模式通常是我之前引用的小部件示例中使用的。

【讨论】:

  • @Emilie Cormier:+1 提供有价值的答案。嗨,艾米莉,谢谢。你明白我的问题的重点。我需要知道这个例子在技术上是否可以接受。 back pointer 和 back reference 的术语对我来说是新的。我将对此进行更多研究。请问使用反向引用而不是反向指针有什么好处吗?
  • @Bunkai:我纠正了我在回答中犯的一些错误,所以你可能想重新阅读它。我不应该在我累的时候回答问题。 :-)
  • @Emilie Cormier:感谢您的额外帖子。是的,情况将会如此。那么,万一我超出了类的范围,内存仍然可以访问吗?我知道 std::vector 会随着它的增长而移动到不同的位置,但是范围外对象的可访问性是我正在考虑的另一个想法。
  • @Emilie:是的,欧洲现在是上午 9:20,我也很累。我昨晚没睡.. :-) 非常感谢您的建议。动态分配应该可以解决问题,但是,正如您所提到的,它会更加混乱。另一种选择是使用数组,或者保留足够大的向量大小,以便它们在想要增长时不必移动?
  • @Emilie:当对象插入vector 时,地址错误的问题已经发生,因为随后它们被复制,并且它们的地址发生了变化。
【解决方案2】:

也许您的所有对象都可以继承自一个通用接口,例如:

class MyObject
{
public:
    virtual int getData() = 0;
}

在你可以使用 stl 库中的 std::tree 来构建你的结构之后。

【讨论】:

  • 没有 std::tree 这样的东西。
  • 嗨,克里斯,使用容器也可能是另一种可能性。我的应用程序处理文件目录结构,所以我的设计对我来说是合乎逻辑的,因为它反映了目录和子目录的级联。如果我开始失去对我的设计的控制,我会切换到另一个设计。
【解决方案3】:

正如 Emile 所说,分段错误是由重新分配引起的。确切地说——当本地堆栈对象的'this'指针被传递以创建另一个对象,然后将其复制到向量容器中。然后'Create()'函数退出,栈帧对象不复存在,容器中的指针失效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 2023-02-01
    • 2012-05-13
    • 1970-01-01
    • 2013-03-05
    相关资源
    最近更新 更多