"Scot T Brennecke" <ScotB@Spamhater.MVPs.org> a ?crit dans le message de
news: %23aAM18sKKHA.3708@TK2MSFTNGP02.phx.gbl...
A virtual destructor only helps to make sure the most-derived destructor
is actually called. If this is a sub-object aggregated into another
object, you've still got big trouble.
Ok.
I juste made a small test for checking that again (see below).
Whatever "this" pointer I use for deletion, the result is the same, and all
destructors are called in the same order (which is the reverse of
construction order).
But maybe I didn't make there a proper "sub-object aggregated into another
object" ?
Of course I will never declare such objects as flat members of other objects
(if needed, I'll use pointers to these objects, likely protected by
CComPtr).
Please could you either modify my code or provide a sample in order to
illustrate what you are saying ?
Gilles
------------------------------------------------
#include <iostream>
using namespace std;
// Just for easily checking what happens if you remove "virtual" in front of
destructors
#define VIRTUAL virtual
class V
{
char * szData;
public:
V() : szData("V") {
cout << "calling V constructor, szData=" << szData << endl;
}
V * get_V_this() {
return this;}
VIRTUAL ~V() {
cout << "calling V destructor, szData=" << szData << endl;
}
};
class W : public virtual V
{
char * szData;
public:
W() : szData("W") {
cout << "calling W constructor, szData=" << szData << endl;
}
W * get_W_this() {
return this;}
VIRTUAL ~W() {
cout << "calling W destructor, szData=" << szData << endl;
}
};
class X : public virtual V
{
char * szData;
public:
X() : szData("X") {
cout << "calling X constructor, szData=" << szData << endl;
}
X * get_X_this() {
return this;}
VIRTUAL ~X() {
cout << "calling X destructor, szData=" << szData << endl;
}
};
class Y
{
char * szData;
public:
Y() : szData("Y") {
cout << "calling Y constructor, szData=" << szData << endl;
}
Y * get_Y_this() {
return this;}
VIRTUAL ~Y() {
cout << "calling Y destructor, szData=" << szData << endl;
}
};
class Z
{
char * szData;
public:
Z() : szData("Z") {
cout << "calling Z constructor, szData=" << szData << endl;
}
Z * get_Z_this() {
return this;}
VIRTUAL ~Z() {
cout << "calling Z destructor, szData=" << szData << endl;
}
};
class B : public W, public X, public Y
{
char * szData;
public:
B() : szData("B") {
cout << "calling B constructor, szData=" << szData << endl;
}
B * get_B_this() {
return this;}
VIRTUAL ~B() {
cout << "calling B destructor, szData=" << szData << endl;
}
};
class A : public Z, public B
{
char * szData;
public:
A() : szData("A") {
cout << "calling A constructor, szData=" << szData << endl;
}
VIRTUAL ~A() {
cout << "calling A destructor, szData=" << szData << endl;
}
};
int main(int argc, char * argv[])
{
A * ptA;
ptA = new A;
cout << "*** deleting A instance by A::this = 0x" << hex << ptA << endl;
delete ptA;
cout << "-----------------" << endl;
ptA = new A;
B * ptB = ptA->get_B_this();
cout << "*** deleting A instance by B::this = 0x" << hex << ptB << endl;
delete ptB;
cout << "-----------------" << endl;
ptA = new A;
V * ptV = ptA->get_V_this();
cout << "*** deleting A instance by V::this = 0x" << hex << ptV << endl;
delete ptV;
cout << "-----------------" << endl;
ptA = new A;
W * ptW = ptA->get_W_this();
cout << "*** deleting A instance by W::this = 0x" << hex << ptW << endl;
delete ptW;
cout << "-----------------" << endl;
ptA = new A;
X * ptX = ptA->get_X_this();
cout << "*** deleting A instance by X::this = 0x" << hex << ptX << endl;
delete ptX;
cout << "-----------------" << endl;
ptA = new A;
Y * ptY = ptA->get_Y_this();
cout << "*** deleting A instance by Y::this = 0x" << hex << ptY << endl;
delete ptY;
cout << "-----------------" << endl;
ptA = new A;
Z * ptZ = ptA->get_Z_this();
cout << "*** deleting A instance by Z::this = 0x" << hex << ptZ << endl;
delete ptZ;
return 0;
}
------------------------------------------------
Output when running the above code :
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by A::this = 0x00367178
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by B::this = 0x00367180
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by V::this = 0x003671A0
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by W::this = 0x00367188
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by X::this = 0x00367190
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by Y::this = 0x00367180
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
-----------------
calling V constructor, szData=V
calling Z constructor, szData=Z
calling W constructor, szData=W
calling X constructor, szData=X
calling Y constructor, szData=Y
calling B constructor, szData=B
calling A constructor, szData=A
*** deleting A instance by Z::this = 0x00367178
calling A destructor, szData=A
calling B destructor, szData=B
calling Y destructor, szData=Y
calling X destructor, szData=X
calling W destructor, szData=W
calling Z destructor, szData=Z
calling V destructor, szData=V
All your examples do not exhibit any aggregation. I think you understand the potential problem if you had