Inside a constructor: can you assign the "this" pointer to a sub-object?

C

craig

During construction of an object "parent", if you create a subobject
that stores a pointer to the parent (through the "this" pointer), will
that pointer be valid when the subobject is later called?

class Parent
{
Parent::parent() { child = new Child( this) };
Child *child;
};

class Child
{
Child::Child( Parent *par) { myParent = par };
Parent *myParent;
}

Will myParent be the correct address when child is subsequently
accessed?

Any comments greatly appreciated.

Craig
 
H

Heinz Ozwirk

craig said:
During construction of an object "parent", if you create a subobject
that stores a pointer to the parent (through the "this" pointer), will
that pointer be valid when the subobject is later called?

class Parent
{
Parent::parent() { child = new Child( this) };
Child *child;
};

class Child
{
Child::Child( Parent *par) { myParent = par };
Parent *myParent;
}

Will myParent be the correct address when child is subsequently
accessed?

As long as your new instance of Child does only save a copy of the pointer
for later use, it is safe. If -- in Child's constructor -- it uses the
pointer to access data or non-static functions of its parent, that may
result in unexpected or even undefined behaviour.

Imagin there are other classes derived from Parent and Parent has virtual
functions. If Child's constructor calls one of these virtual functions, the
implementation provided by Parent intself will be called, never that of a
derived class. If it is a pure virtual function, you'll have a problem.

The Parent object passed to child might not be properly initialized. Any
initialization Parent's constructor does after create a new Child, will not
be visible to the Child (or to any functions of Parent, which Child might
call) until Parent's constructor has been completed. Even though all bases
and members of Parent have been constructed once exceution of a constructors
body starts, that does not always gurantee that the object is in a well
defined state.

Think about (a poorly designed) class like

class Parent
{
int x;
Child* child;
...
public:
int GetX() const { return x; }
Parent()
{
child = new Child(this);
x = 0;
}
...
};

If Child's constructor would call Parent::GetX on its input object, it would
get some random value.

HTH
Heinz
 
R

Roland Pibinger

During construction of an object "parent", if you create a subobject
that stores a pointer to the parent (through the "this" pointer), will
that pointer be valid when the subobject is later called?

class Parent
{
Parent::parent() { child = new Child( this) };
Child *child;
};

class Child
{
Child::Child( Parent *par) { myParent = par };
Parent *myParent;
}

Will myParent be the correct address when child is subsequently
accessed?
Any comments greatly appreciated.

That's a common problem when you want to use back-pointers. Compilers
usually issue a warning. You may use it but it's unsafe for some cases
(see Heinz Ozwirk's post). For a really safe implementation you would
need some kind of 2-phase initialization (Child registers with Parent
when all constructor initialization is done). Alternatively you may
initialize child on demand and access it only with a get-function:

class Parent
{
// ...
Parent::parent(): child(0) {};
Child* getChild() {
if (!child) {
child = new Child( this);
}
return child;
}
private:
Child *child;
};

The above is only possible when you use a pointer to Child as member
in Parent (which you usually try to avoid).

Best wishes,
Roland Pibinger
 
C

craig

Thanks Roland, what you mention seems to be my problem,. because I can
correct it by initializing the back-pointer outside of the parent
constructor (after the construction is complete).

Originally the back-pointer that I created in the parent constructor
seemed like a valid pointer (in that it pointed to the right object),
but when one of the child members tried to access a parent variable
after one of the its variables had subsequently changed, the variable's
value was still at it's original (construction-time value). By setting
the back-pointer after the parent constructor completed, the
back-pointer was different, and would also reflect the updated parent
variable correctly.

-Craig
 
C

craig

Heinz,

Thanks so much for the helpful remarks. I learned a few things. It
seems like your remarks also explained my situation, but not sure. If
you have a moment, see my response to Roland where I explain the
behavior briefly.

Thanks again, craig
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top