Sign in to follow this  
Decrius

[C++] Delete base class pointer which actually holds a derived class pointer?

Recommended Posts

Is this perfectly safe?
#include <iostream>

class CBase {};
class CDerived : public CBase {};

int main ()
{
    CBase* b = new CDerived;
    delete b;
    return 0;
}

I have an array of base pointers, which is filled with derived pointers of that base class. Is it safe to delete it? Should I cast it first to the derived class (how do I know which class I have filled it with? ^^). Unsure if it's safe, how would it know the size it has to deallocate? I still wonder how you can ever fill a base class pointer with a derived class pointer, they both differ in size, don't they? Thanks.

Share this post


Link to post
Share on other sites
As long as your base class has a virtual destructor, this is fine.

Quote:

I still wonder how you can ever fill a base class pointer with a derived class pointer, they both differ in size, don't they?


A derived class is a base class. And you don't "fill" a pointer with an object, you point at an object with a pointer.

Share this post


Link to post
Share on other sites
Yea as far as I know the code is fine. You do not need to cast it, but the base class should have a virtual destructor.

Each compiler has it's own mechanism for determining what the size is. Don't worry about it !!

EDIT : damn .. to slow !!

Share this post


Link to post
Share on other sites
To see how making the destructor virtual makes a difference you might try this:


#include <iostream>
using std::cout;

struct A
{
A() { cout << "A()\n"; }
//virtual
~A() { cout << "~A()\n"; }
};

struct B: public A
{
B() { cout << "B()\n"; }
~B() { cout << "~B()\n"; }
};

int main()
{
A* p = new B;
delete p;
}





The B part of the object is never destructed and that's undefined behaviour.

Now comment in the virtual keyword. Now at run-time the destructor for both parts of *p are called, as the virtual keyword tells it to start destructing from the actual most derived type of *p and call all the destructors all the way up to that of the parent.

Share this post


Link to post
Share on other sites
So, a virtual is usefull for when you have a base class pointer filled with a derived class pointer?

As for the compiler-time, I referred to the sizes of what should be deallocated ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by Decrius
So, a virtual is usefull for when you have a base class pointer filled with a derived class pointer?

As for the compiler-time, I referred to the sizes of what should be deallocated ;)


Once again, as Driv3MeFar already pointed out, you don't "fill" pointers. You allocate memory somewhere and the pointer points to the address in memory where that section begins.

Share this post


Link to post
Share on other sites
The problem isn't that he gets what you mean. The concern is that you may not quite understand what you're saying. They're trying to help. :)

If you "fill" a pointer with a value, then you would be treating the pointer as some form of data structure - a way to store various bits of information in memory in different ways.

What you need to understand is you're not actually "filling" the pointer. What you have is a pointer that contains a value, much like an integer or float contains a value. And, just like an integer, a pointer takes up a few bytes in memory (size varies based on your architecture, 16-bit, 32-bit, 64-bit, or whatever). These few bytes are only used to store a memory address. That's it, nothing else. This memory address is located completely separate of the pointer, at some random location in memory and you don't care where.

Quote:

As for the compiler-time, I referred to the sizes of what should be deallocated ;)


Again, no. Virtual functions are handled at run-time. As are allocations and deallocations. Consider:


#include <iostream>
using namespace std;

class A
{
public:
A() { cout << "A()" << endl; }
virtual ~A() { cout << "~A()" << endl; }
private:
};

class B : public A
{
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
private:
};

int main()
{
char input;
A* obj;


cout << "Enter 1 or 2: ";
cin >> input;

if ( input == '1' ) { obj = new A; }
else { obj = new B; }

delete obj;

return 0;
}





You can enter 1 or 2. At compile time, the code doesn't know which variable obj will be allocated to when it calls delete. Nor does it care. It's handled at run time. This is even the case if you don't use virtual methods. However, to ensure your destructor is run for your derived class (and any other methods you may choose to override in the derived class that are in the base class), you need to be virtual.

Share this post


Link to post
Share on other sites
Sorry to say, but what else are you doing then filling the pointer (and possibly allocating data) here?

int *pointer; // random value, w/e was in there
pointer = new int(5); // I FILL the pointer with a memory address pointing to an interger with the value 5
delete pointer;
pointer = NULL; // I fill the pointer with w/e NULL holds


I can't think of a better name really...

Quote:
Original post by CaspianB
You can enter 1 or 2. At compile time, the code doesn't know which variable obj will be allocated to when it calls delete. Nor does it care. It's handled at run time. This is even the case if you don't use virtual methods. However, to ensure your destructor is run for your derived class (and any other methods you may choose to override in the derived class that are in the base class), you need to be virtual.


Ah, I see your point, but how does it safe that information at run-time? At a special memory place?

Share this post


Link to post
Share on other sites
Quote:
Original post by Decrius
I can't think of a better name really...
The technical and commonly used term is 'assign' (from 'assignment'). You assign the newly created lvalue to the pointer. The term 'fill' usually has another meaning (see, for instance, std::fill) which relates to filling a sequence with copies of an object.

Quote:
Ah, I see your point, but how does it safe that information at run-time? At a special memory place?


Yes, it does. Where the data is saved depends on the compiler and the compiler settings (for instance, it can be stored as part of a virtual table).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this