Re: Unusual usage of IUknown
- From: Scot T Brennecke <ScotB@xxxxxxxxxxxxxxxxxx>
- Date: Tue, 01 Sep 2009 22:43:24 -0500
Gingko wrote:
"Scot T Brennecke" <ScotB@xxxxxxxxxxxxxxxxxx> a écrit dans le message de news: %23aAM18sKKHA.3708@xxxxxxxxxxxxxxxxxxxxxxxA 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
class V
{
char * szData;
ULONG m_cRef;
public:
V() : szData("V") {}
VIRTUAL ~V() {}
ULONG STDMETHODCALLTYPE CUnknownStub::Release()
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
};
class W
{
V v;
char * szData;
public:
W() : szData("W") {}
VIRTUAL ~W() {}
};
.
- Follow-Ups:
- Re: Unusual usage of IUknown
- From: Gingko
- Re: Unusual usage of IUknown
- References:
- Re: Unusual usage of IUknown
- From: Ben Voigt [C++ MVP]
- Re: Unusual usage of IUknown
- From: Gingko
- Re: Unusual usage of IUknown
- From: Scot T Brennecke
- Re: Unusual usage of IUknown
- From: Gingko
- Re: Unusual usage of IUknown
- Prev by Date: Re: void* passed as funtion parameters?
- Next by Date: Re: void* passed as funtion parameters?
- Previous by thread: Re: Unusual usage of IUknown
- Next by thread: Re: Unusual usage of IUknown
- Index(es):
Relevant Pages
|