virtual destructor problem

L

lmfmaw

Hi all,

I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..

Please can someone help me clean up properly?
--------

#include <iostream>
using namespace std;

class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;

};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;

};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);

for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}
 
A

Alf P. Steinbach

* (e-mail address removed):
Hi all,

I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..

Please can someone help me clean up properly?
--------

#include <iostream>
using namespace std;

class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;

};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;

};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);

for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}


The direct answer is to call

delete anBase[0];
delete anBase[1];

However, you can automate that by using e.g. boost::shared_ptr<Base>
instead of Base*.

And instead of a raw array it would be a good idea to use a std::vector,
just to get into that habit.

Cheers, & hth.,

- Alf
 
R

Rahul

Hi all,

I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..

Please can someone help me clean up properly?
--------

#include <iostream>
using namespace std;

class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;

};

class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;

};

int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);

for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;

}


As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.
 
A

Abhishek Padmanabh

I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..
Please can someone help me clean up properly?
--------
#include <iostream>
using namespace std;
class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;

class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;

int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);
for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;


As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.- Hide quoted text -


There is "need" for the base destructor to be declared virtual because
otherwise the following will not work:

delete anBase[0];
delete anBase[1];
 
R

Rahul

On Dec 9, 5:16 pm, (e-mail address removed) wrote:
Hi all,
I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..
Please can someone help me clean up properly?
--------
#include <iostream>
using namespace std;
class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;
};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;
};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);
for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}

As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.- Hide quoted text -

There is "need" for the base destructor to be declared virtual because
otherwise the following will not work:

delete anBase[0];
delete anBase[1];


In the sense, it just wouldn't invoke the derived class destructor and
as the derived class destructor is not doing anything.
I don't see any negative impact. Yes i'm not saying it is a thumb
rule...
 
A

Abhishek Padmanabh

On Dec 9, 5:16 pm, (e-mail address removed) wrote:
Hi all,
I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..
Please can someone help me clean up properly?
--------
#include <iostream>
using namespace std;
class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;
};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;
};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);
for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}
As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.- Hide quoted text -

There is "need" for the base destructor to be declared virtual because
otherwise the following will not work:
delete anBase[0];
delete anBase[1];

In the sense, it just wouldn't invoke the derived class destructor and
as the derived class destructor is not doing anything.
I don't see any negative impact. Yes i'm not saying it is a thumb
rule...



The negative impact is that it is undefined behaviour as per the
standards. What bad will happen depends on the particular
implementation. May cause a memory leak. I cannot comprehend what else
can go wrong in cases of undefined behaviours.
 
R

Rahul

On Dec 9, 5:47 pm, Abhishek Padmanabh <[email protected]>
wrote:
On Dec 9, 5:16 pm, (e-mail address removed) wrote:
Hi all,
I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..
Please can someone help me clean up properly?
--------
#include <iostream>
using namespace std;
class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;
};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;
};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);
for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}
As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.- Hide quoted text -
There is "need" for the base destructor to be declared virtual because
otherwise the following will not work:
delete anBase[0];
delete anBase[1];

In the sense, it just wouldn't invoke the derived class destructor and
as the derived class destructor is not doing anything.
I don't see any negative impact. Yes i'm not saying it is a thumb
rule...

The negative impact is that it is undefined behaviour as per the
standards. What bad will happen depends on the particular
implementation. May cause a memory leak. I cannot comprehend what else
can go wrong in cases of undefined behaviours.


Oh, if that is the case, why does't the standard mandate dest to be
always virtual when some other function is also virtual in the base
class? It would be easy for the compiler to spot out the error too,
isn't it?
 
B

Bo Persson

Rahul wrote:
:: On Dec 9, 6:02 pm, Abhishek Padmanabh
:::
:::
:::
:::: On Dec 9, 5:47 pm, Abhishek Padmanabh
:::
:::
:::::: On Dec 9, 5:16 pm, (e-mail address removed) wrote:
:::
::::::: Hi all,
:::
::::::: I've hit the wall with this "fairly" simple problem. As you
::::::: can see in the code below, my destructors don't do their job
::::::: as they are supposed to (I left them empty for this example).
::::::: I'm running the Visual Leak Detector library (on VS 2005) to
::::::: detect memory leaks and whatever I've tried it still
::::::: complains..
:::
::::::: Please can someone help me clean up properly?
::::::: --------
:::
::::::: #include <iostream>
::::::: using namespace std;
:::
::::::: class Base {
::::::: public:
::::::: Base(int baseInt) { m_baseInt=baseInt; }
::::::: virtual ~Base() {}
::::::: virtual void behave() const { cout << "I'm Base." <<
::::::: endl; } virtual void prnt() const { cout << m_baseInt <<
::::::: endl; } int m_baseInt;
:::
::::::: };
:::
::::::: class Derived : public Base {
::::::: public:
::::::: Derived(int baseInt, int derivedInt): Base(baseInt)
::::::: { m_derivedInt=derivedInt; }
::::::: ~Derived() {}
::::::: void behave() const { cout << "I'm Derived!" << endl; }
::::::: void prnt() const { cout << m_baseInt << " : " <<
::::::: m_derivedInt << endl; }
::::::: private:
::::::: int m_derivedInt;
:::
::::::: };
:::
::::::: int main() {
::::::: Base *anBase[2];
::::::: anBase[0] = new Base(11);
::::::: anBase[1] = new Derived(100, 1907);
:::
::::::: for(int i = 0; i < 2; i++) {
::::::: anBase->behave();
::::::: anBase->prnt();
::::::: }
::::::: return 0;
:::
::::::: }
:::
:::::: As your derived class as well as base class destructor's
:::::: aren't doing
:::::: anything, there is no need for them to be declared as
:::::: virtual.- Hide quoted text -
:::
::::: There is "need" for the base destructor to be declared virtual
::::: because otherwise the following will not work:
:::
::::: delete anBase[0];
::::: delete anBase[1];
:::
:::: In the sense, it just wouldn't invoke the derived class
:::: destructor and as the derived class destructor is not doing
:::: anything.
:::: I don't see any negative impact. Yes i'm not saying it is a thumb
:::: rule...
:::
::: The negative impact is that it is undefined behaviour as per the
::: standards. What bad will happen depends on the particular
::: implementation. May cause a memory leak. I cannot comprehend what
::: else can go wrong in cases of undefined behaviours.
::
:: Oh, if that is the case, why does't the standard mandate dest to be
:: always virtual when some other function is also virtual in the base
:: class? It would be easy for the compiler to spot out the error too,
:: isn't it?

But it is only an error if you do a delete through a pointer to base.
If you just have a local Derived variable, or use a pointer to
Derived, it is ok.


Bo Persson
 
S

Salt_Peter

On Dec 9, 5:16 pm, (e-mail address removed) wrote:
Hi all,
I've hit the wall with this "fairly" simple problem. As you can see in
the code below, my destructors don't do their job as they are supposed
to (I left them empty for this example). I'm running the Visual Leak
Detector library (on VS 2005) to detect memory leaks and whatever I've
tried it still complains..
Please can someone help me clean up properly?
--------
#include <iostream>
using namespace std;
class Base {
public:
Base(int baseInt) { m_baseInt=baseInt; }
virtual ~Base() {}
virtual void behave() const { cout << "I'm Base." << endl; }
virtual void prnt() const { cout << m_baseInt << endl; }
int m_baseInt;
};
class Derived : public Base {
public:
Derived(int baseInt, int derivedInt): Base(baseInt)
{ m_derivedInt=derivedInt; }
~Derived() {}
void behave() const { cout << "I'm Derived!" << endl; }
void prnt() const { cout << m_baseInt << " : " << m_derivedInt <<
endl; }
private:
int m_derivedInt;
};
int main() {
Base *anBase[2];
anBase[0] = new Base(11);
anBase[1] = new Derived(100, 1907);
for(int i = 0; i < 2; i++) {
anBase->behave();
anBase->prnt();
}
return 0;
}
As your derived class as well as base class destructor's aren't doing
anything, there is no need for them to be declared as virtual.- Hide quoted text -

There is "need" for the base destructor to be declared virtual because
otherwise the following will not work:
delete anBase[0];
delete anBase[1];

In the sense, it just wouldn't invoke the derived class destructor and
as the derived class destructor is not doing anything.
I don't see any negative impact. Yes i'm not saying it is a thumb
rule...


If you allocate and store objects using a pointer to a base class,
the standard requires the base class destructor to be virtual.

Don't get fooled by an empty d~tor body, they may now (or later in
your developmental process) invoke other destructors (ie: member
d~tors). In this scenario you have integer members so those d~tors are
definitely doing something.
 
P

Pete Becker

If you allocate and store objects using a pointer to a base class,
the standard requires the base class destructor to be virtual.

No, it doesn't. The relevant requirement is that if you delete an
object of a derived type through a pointer to one of its base types and
that base type does not have a virtual destructor, the behavior of the
program is undefined. That is, a virtual destructor is required if you
delete the object through a pointer to base. Not if you only allocate
and store it.
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top