从包含对象访问包含对象的成员
如果我有多个级别的对象包含(一个对象定义并实例化另一个对象,该对象定义并实例化另一个对象..),是否可以访问上层,包含 - 对象变量和函数,请问?
示例:
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;
但是,在编译并运行我的应用程序后,我收到内存访问冲突错误。
- 上面的代码有什么问题(这是示例,可能包含拼写错误)?
- 我是否必须动态而不是静态创建对象?
- 有没有其他方法可以从包含对象中获取存储在包含对象中的变量?
If I have several levels of object containment (one object defines and instantiates another object which define and instantiate another object..), is it possible to get access to upper, containing - object variables and functions, please?
Example:
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;
}
Say, that from within CObjectThree I need to access nVariableOne in CObjectOne. I would like to do it as follows:
int nValue = vObjectThree[index].GetObjectTwo()->GetObjectOne()->nVariable1;
However, after compiling and running my application, I get Memory Access Violation error.
- What is wrong with the code above(it is example, and might contain spelling mistakes)?
- Do I have to create the objects dynamically instead of statically?
- Is there any other way how to achieve variables stored in containing objects from withing contained objects?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您传递一个指向容器对象的指针时,该指针有时称为后退指针。我发现这种技术一直在 GUI 库中使用,其中小部件可能需要访问其父小部件。
话虽这么说,您应该问自己是否有更好的设计不涉及循环依赖(循环是指容器依赖于容器,而容器又依赖于容器)。
您不必严格必须动态创建对象才能使后指针技术发挥作用。您始终可以获取堆栈分配(或静态分配)对象的地址。 只要该对象的生命周期持续存在,而其他人正在使用指向该对象的指针。但在实践中,此技术通常用于动态创建的对象。
请注意,您也许还可以使用反向引用而不是反向指针。
我想我知道是什么导致了你的分段错误。当向量重新分配内存(由于增长到更大的大小)时,旧向量元素的地址将变得无效。但是这些对象的子对象(和孙对象)仍然在其后向指针中保留旧地址!
为了使后向指针起作用,您必须动态分配每个对象并将它们的指针存储在向量中。这将使内存管理变得更加混乱,因此您可能需要使用智能指针或 boost::ptr_containers。
看到您在另一个答案中发表的评论后,我现在对您想要完成的任务有了更好的了解。您应该研究通用树结构和复合模式。复合模式通常是我之前引用的小部件示例中使用的模式。
When you pass a pointer that points back to the container object, this pointer is sometimes called a back pointer. I see this technique being used all the time in GUI libraries where a widget might want access to its parent widget.
That being said, you should ask yourself if there's a better design that doesn't involve circular dependencies (circular in the sense that the container depends on the containee and the containee depends on the container).
You don't strictly have to create the objects dynamically for the back pointer technique to work. You can always take the address of a stack-allocated (or statically-allocated) object. As long as the life of that object persists while others are using pointers to it. But in practice, this technique is usually used with dynamically-created objects.
Note that you might also be able to use a back-reference instead of a back-pointer.
I think I know what's causing your segmentation faults. When your vectors reallocate their memory (as the result of growing to a larger size), the addresses of the old vector elements become invalid. But the children (and grand-children) of these objects still hold the old addresses in their back-pointers!
For the back-pointer thing to work, you'll have to allocate each object dynamically and store their pointers in the vectors. This will make memory management a lot more messy, so you might want to use smart pointers or boost::ptr_containers.
After seeing the comment you made in another answer, I now have a better idea of what you're trying to accomplish. You should research generic tree structures and the composite pattern. The composite pattern is usually what's used in the widget example I cited previously.
也许您的所有对象都可以从一个通用接口继承,例如:
然后您可以使用 stl 库中的 std::tree 来构建您的结构。
Maybe all your object can inherit from a common interface like :
And after you can use a std::tree from the stl library to build your structure.
正如Emile所说,分段错误是由重新分配引起的。确切地说,当传递本地堆栈对象的“this”指针来创建另一个对象时,该对象随后被复制到向量容器中。然后“Create()”函数退出,堆栈帧对象不再存在,容器中的指针变得无效。
As Emile said, segmentation fault is caused by reallocation. Exactly speaking -- when the local stack objects' 'this' pointer was passed to create another object, which is then copied to the vector container. Then the 'Create()' function exits, the stack frame object ceases to exist and the pointer in the container gets invalid.