0

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?
Bunkai.Satori
  • 4,698
  • 13
  • 49
  • 77
  • 1
    Your code is not correct. All members of all your classes are private, so this would never compile. Also, your class-definitions have to be finished by a semicolon. Please post correct, working code that reproduces the error. – Björn Pollex Mar 08 '11 at 07:18
  • @Space_C0wb0Y: Hi, thanks for your comment. I would liek to post my original code, However, I have it distributed over several class files. To show my code, I would have to add tons of text. I was interested basically in the principle if refering to containing object via **this** should work even if objects are created statically. – Bunkai.Satori Mar 08 '11 at 07:23
  • 1
    If you want a good answer, you will have to put some work into the question. This may include writing a small example application that actually compiles and reproduces the error. It is very hard to find the cause of an error without seeing the actual code that causes it. – Björn Pollex Mar 08 '11 at 07:29

3 Answers3

1

Maybe all your object can inherit from a common interface like :

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

And after you can use a std::tree from the stl library to build your structure.

chris
  • 91
  • 1
  • 1
  • 6
  • There's no such thing as std::tree. – Emile Cormier Mar 08 '11 at 07:50
  • Hi chris, using containers could be another possibility as well. My application processes file directory structure, so my design came logical to me, as it reflects the cascading of directories and subdirectories. If I start losing control over my design, i will switch to another design. – Bunkai.Satori Mar 08 '11 at 08:02
1

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.

Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
  • @Emilie Cormier: +1 for valuable answer. Hi Emilie, thanks. You understood the point of my question. I needed to know if the the example is technically acceptable. The terminology of **back pointer** and **back reference** is new to me. I will study more about it. Is there any advantage of using back reference over back pointer, please? – Bunkai.Satori Mar 08 '11 at 07:59
  • @Bunkai: I corrected a few blunders I made in my answer, so you might want to re-read it. I shouldn't be answering stuff when I'm tired. :-) – Emile Cormier Mar 08 '11 at 08:17
  • @Emilie Cormier: thank you for your additional post. Yes, that will be the case. So, in case, I get out of the scope of the classes, will the memory be still accessible? I understand that the std::vector<> gets moved to different location as it grows, but accessiblity of out of the scope objects was another think I was considering. – Bunkai.Satori Mar 08 '11 at 08:20
  • @Emilie: Yeah, It is 9:20am in Europe, and I am pretty tired as well. I did not sleep last night.. :-) Thank you very much for your advices. Dynamic allocation should solve the problem, although, it will be more messy, as you mentioned. Another alternative could be using arrays, or reserving vector sizes large enough so they do not have to move when they want to grow? – Bunkai.Satori Mar 08 '11 at 08:23
  • @Emilie: The problem with the bad addresses happens already when the objects are inserted into the `vector`, because then they are copied, and their addresses change. – Björn Pollex Mar 08 '11 at 08:29
  • @Emilie: Thanks for your precious advices. This answer is a candidate for the *Accepted Answer*. However, I would still like to keep it open for some more time, to see if I get additional answers. – Bunkai.Satori Mar 08 '11 at 08:30
  • @Bunkai: Heap-allocated objects are accessible in all scopes, as long as there's a way to obtain a pointer to said object. – Emile Cormier Mar 08 '11 at 08:32
  • @Space_C0wb0y: so, apparently, dynamic memory allocations would be the direct solution of this problem. However, there might be better soultions, as Emilie proposed. – Bunkai.Satori Mar 08 '11 at 08:33
  • BTW, it's EMILE (masculine) not EMILIE (feminine). :-) – Emile Cormier Mar 08 '11 at 08:35
  • @Bunkai: The Composite Pattern indeed uses dynamic allocation. Find and study some examples of the Composite Pattern in C++, and everything will become much clearer. Sorry for my late-night incoherent blatherings. :-) – Emile Cormier Mar 08 '11 at 08:38
  • I've just redone my problem into dynamiccaly allocated objects, and I can confirm, that the dynamic solution works. – Bunkai.Satori Mar 08 '11 at 08:57
0

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.

gkolarov
  • 21
  • 2