#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
};
class derv :public base
{
int b;
public:
derv() {b =1;}
};
int main()
{
base *pb = new derv();
delete pb;
}
I don't have a virtual destructor in derv class, does it delete only base part of derv object??
It might.
Because base does not have a virtual destructor, your code exhibits undefined behavior. Anything might happen. It might appear to work as you expect. It might leak memory. It might cause your program to crash. It might format your hard drive.
A citation was requested. C++11 ยง5.3.5/3 states that, for a scalar delete expression (i.e., not a delete[] expression):
if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined.
The static type (base) is different from the dynamic type (derv) and the static type does not have a virtual destructor, so the behavior is undefined.
In your source code there is no memory leak, since you don't have any member variable that is created dynamically.
Consider the modified example below Case 1:
#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
~base()
{
cout<<"\nBase Destructor called";
}
};
class derv :public base
{
int *b;
public:
derv() { b = new int;}
~derv()
{
cout<<"\nDerv Destructor called";
delete b;
}
};
int main()
{
base *pb = new derv();
delete pb;
}
In this case the output will be,
Base Destructor called
In this case there is a memory leak, because 'b' is created dynamically using 'new' which should be deleted using 'delete' keyword. Since derv destructor is not being called it's not deleted so there is memory leak.
Consider the below case 2:
#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
virtual ~base()
{
cout<<"\nBase Destructor called";
}
};
class derv :public base
{
int *b;
public:
derv() { b = new int;}
~derv()
{
cout<<"\nDerv Destructor called";
delete b;
}
};
int main()
{
base *pb = new derv();
delete pb;
}
In the case 2 output will be,
Derv Destructor called
Base Destructor called
In this case there is no memory leak.because derv destructor is called and b is getting deleted.
Destructor can be defined as Virtual in base class to make sure the derived class destructor to be called when we delete base class pointer which is pointing to derived class object.
We can say 'Destructor must be virtual when derived class has dynamically created members'.
There is no memory leak in your code. There would have been a memory leak if you needed to free some memory in the derived class destructor.
Related
Does the following case has memory leak? I suppose in foo(), the delete *e only sees the base part of the object. What about *e = NULL, is this refers to the Base object as well?
Sorry to mention, I used gcc4.4.7.
What is the good way of doing it? Any suggestion is appreciate!
class Base
{
public:
Base() {}
virtual ~Base() {}
virtual bool valid() { return true; }
}
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
bool valid() { return false; }
}
void foo(Base** e)
{
if((*e)->valid() {
cout << "is valid";
}
else{
cout<< " not valid";
delete *e;
*e = NULL;
}
}
int main()
{
Derived* d = new Derived;
Base* cast_d = static_cast<Base*>(d);
foo(&cast_d);
}
That is not at all a memory leak. When we delete a base class pointer if the base class pointer is holding the address of a derive class object it will first call derived class destructor if that is declared virtual. That is the reason why we have virtual destructor but not virtual constructor in C++. If we are using a Base class pointer to store the address of various derived classes pointers we should always declare the derived class destructor as virtual so that memory release should done in correct order.
Hope this will help you.
In the code there is no memory leak
the virtual destructor, allows any derived class to be properly destroyed.
If a Base * was passed into foo, it would not get destroyed, so it may leak . But that is not in the code presented.
I have a class that has a std::vector of pointers to a base class that has different derived classes. How do I call their destructors from within the vector class?
holder.h
class holder
{
public:
void add_stuff();
void do_stuff();
private:
std::vector<base*> vect;
};
holder.cpp
void holder::add_stuff(base* to_add) {
vect.push_back(to_add);
}
void holder::do_stuff() {
vect[0]->say_words();
delete vect[0]; //<--<--<-- I want to delete the object now
}
Feel free to stop now if you know what I'm doing wrong. I've included the basics of what the rest of the code looks like, in case I'm just way off.
base.h
class base
{
public:
base();
virtual ~base();
virtual void say_words() = 0;
};
derived.h
class derived : public base
{
public:
derived();
~derived();
void say_words();
};
derived.cpp
derived::derived() {}
derived::~derived() {}
void derived::say_words() {
cout << "Words!" << endl;
}
main.cpp
holder hold;
holder* H = &hold;
int main(){
base* d = new derived();
H->add_stuff(d);
H->do_stuff();
}
How do I call their destructors from within the vector class?
You already are, by virtue of the fact that the ~base destructor is marked as virtual. Calling delete on a pointer to the base class will automatically call all of the derived destructors for you. That is WHY the base class destructor needs to be declared as virtual in the first place.
What you are missing, though, is removing the object pointer from your std::vector after you delete the object, eg:
void holder::do_stuff() {
vect[0]->say_words();
delete vect[0]; // <-- calls all destructors of this object!
vect.erase(vect.begin()); // <-- add this line!
}
You don't want to leave invalid pointers in your container.
I'm newbie in C++. I'm learning c++ oops concepts. Is it allowed to using Derived class(D) allocate the memory of Base class(B) pointer?
B *a = new D();
My code:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
cout<<"B constructor"<<endl;
}
~B()
{
cout<<"B Destroctur"<<endl;
}
};
class D : public B
{
public:
D()
{
cout<<"D constructor"<<endl;
}
~D()
{
cout<<"D Destroctur"<<endl;
}
};
int main()
{
B *a = new D();
delete a; // Is valid?
}
Also, Is it valid to free the memory of base class pointer?
delete a;
it is valid as long as you declare base destructor virtual:
virtual ~B() { /*B destructot code*/}
What you did was created and object of class D which is derived from class B. Pointer of type B that the address of created object is assigned to is a pointer with instruction to point to "B part of class D". The object created is still of class D and can be cast into class D pointer.
This is also a way to restrict usage of D class functionalities in a current scope or create a list of objects with different types which must all be derived from the same base class (typical example is dog and cat class extend animal class and are both put in pets<animal> list)
As per your code, the output will be
B constructor
D constructor
B Destructor ==> Base class
Derived class memory will not deleted. So avoid that, we need to use virtual keyword in base class destructor.
virtual ~B()
{
cout<<"B Destroctur"<<endl;
}
during run time, while calling base class (B) destructor, it calls derived class destructor (D) and then base class destructor executed.
if base class destructor is virtual, the output will be
B constructor
D constructor
D Destructor ==> Derived class
B Destructor ==> Base class
Is it ok to delete an abstract class instead of a child? Will all allocs be deallocated thereby?
Consider a following situation as an example, but please do not limit your answers to that one case:
struct A {
virtual void fun() = 0;
};
struct B : public A {
void fun() { /* actually doing something here. */ }
};
struct C {
A *a;
void OneTask() {
// (...)
a = new B();
}
void AnotherTask() { /* using fun() in some way. */ }
~C() { delete a; }
};
The idea is to have multiple possible outcomes of OneTask() which result in an assignment of a pointer to different classes that inherit from A, B being just an example; and then to use such result reasonably in AnotherTask() and other methods of class C.
You must have virtual destructor in base class else complete destruction of derived class doesn't happen.
struct A {
virtual void fun() = 0;
virtual ~A()
{
}
};
Yes, it's perfectly fine to delete a without knowing what actual derived type a is pointing to.
As shivakumar pointed out, if you don't make your base class's destructor virtual, then deleting a derived class will not end up calling the base class's destructor. In your trivial example that's not a problem, but in real life you should always make your destructors virtual.
If A has a virtual destructor then both destructors of A and B are succesfully called (first B then A) ,
If you do not declare the constructor of A as virtual, then only the destructor of A is called during deletion and extended data of B may leak.
struct A {
virtual void fun() = 0;
virtual ~A();
};
struct B : public A {
void fun() { /* actually doing something here. */ }
~B();
};
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
When to use virtual destructors?
[Second dicuss]
hi,guys! You are all talking about virtual-destructor.
And also i think about the base class`s destructor.
But another test as this:
class A
{
public:
A()
{
}
virtual void fun()
{
}
private:
int mIntA;
};
when class A have a vitual function(not virtual-destrcutor),
it`s ok. Deleting ptrA is OK!
So, i think A just need a vptr to activate the polymorphic. Not class As
destructor must be virtual.
Class As destructor being not virtual just can make resources is not released
correctly.
class A
{
public:
A()
{
}
/*virtual*/ ~A()
{
}
private:
int mIntA;
};
class B : public A
{
public:
B()
{
mIntB = 1234;
}
virtual ~B()
{
int i = 0;
}
private:
int mIntB;
};
I have a class A. And a class B derived form A;
A doesn`t have any virtual function.
so when i do this:
A* ptrA = new B;
delete ptrA;
it crashes!
but when add a virtual fun to A. it`s ok.
as we know, ptrA is a B object.
but why is it?
The A class isn't polymorphic, therefore the delete has no possibility to know that ptrA actually points inside an allocated block and therefore the deallocation crashes.
You have a non-virtual destructor!
(which means that when the destructor is called, it's A's destructor that is called, rather than B's, even though the object was allocated as a B)