class Z
{
public:
Z(void);
~Z(void);
};
Z::Z(void)
{
cout << "in Z::Z(void)" << endl;
}
Z::~Z(void)
{
cout << "in Z::~Z(void)" << endl;
}
class Y
{
Z *pZ;
public:
Y(void);
~Y(void);
};
Y::Y(void)
{
cout << "in Y::Y(void)" << endl;
pZ = new Z;
}
Y::~Y(void)
{
cout << "in Y::~Y(void)" << endl;
delete pZ;
}
class X
{
Y *pY;
public:
X(void);
~X(void);
};
X::X(void)
{
cout << "in X::X(void)" << endl;
pY = new Y;
}
X::~X(void)
{
cout << "in X::~X(void)" << endl;
delete pY;
}
In this definition, an object of class X has a pointer to
an object of class Y. An object of class Y has a pointer
to point to an object of class Z. What is important here is that
when an X object is created, it also creates an Y
object dynamically. When the Y object is being created, it
also creates a Z object.
Note that the creations of the Y object and the Z object
are implicit. In other words, the following code creates a Y
and a Z without any explicit code:
X myX;
In fact, observe the behavior of the following code:
{
X *myX;
myX = new X;
cout << "in the block" << endl;
delete myX;
}
Here is the sequence:
X
X::X is invoked
Y
Y::Y is invoked
Z
Z::Z is invoked and completes
Z object is reserved and initialized
Z object is stored in pZ of
the Y object
Y::Y completes
Y object is fully initialized
Y object is stored in pY of
the X object
X::X completes
X object is fully initialized
X object is stored in myX
new statement executes
delete myX
X::~X is invoked, it calls
delete pY
Y::~Y is invoked, it calls
delete pZ
Z::~Z is invoked and completed
Z object is freed
Y::~Y completes
Y object is freed
X::~X completes
X object is freed