1

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?

Community
  • 1
  • 1
  • 5
    http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors – Armen Tsirunyan Nov 14 '10 at 16:45
  • 1
    `it crashes!` Because undefined behaviour means anything can happen. – Prasoon Saurav Nov 14 '10 at 16:46
  • 1
    Basically, you are not understanding virtual destructors and why you need to use them in your base classes. The question people are calling an exact duplicate isn't exactly. But all the answers to it will answer your question. – Omnifarious Nov 14 '10 at 16:47

2 Answers2

3

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)

Community
  • 1
  • 1
James
  • 22,556
  • 11
  • 75
  • 125
  • 2
    And because the OP invoked undefined behavior, demons flew out the OPs nose. - http://everything2.com/title/demons+fly+out+your+nose or http://en.wikipedia.org/wiki/C_(programming_language)#Undefined_behavior – Omnifarious Nov 14 '10 at 16:51
  • @Omni Huh? What exactly is undefined about this? – Šimon Tóth Nov 14 '10 at 16:56
  • @Let_Me_Be - Invoking the destructor of a base class on an object of a derived class. See item 20.7 here: http://www.parashift.com/c++-faq-lite/virtual-functions.html – Omnifarious Nov 14 '10 at 17:01
  • @Omni Well, that would be true for a polymorphic class without a virtual destructor. In this case you are effectively calling the destructor of the class `A` for an object of class `A`. The only thing is that this object resides inside a larger memory block. – Šimon Tóth Nov 14 '10 at 17:04
  • 1
    @Let_Me_Be - No, it's undefined in all cases in which you do that. `delete` is not the equivalent of `free`. There is no reason for the compiler to store the size of an allocated block in C++, and regardless, a pointer to a base class instance inside of a derived class may not point to the beginning of the block for any number of reasons. – Omnifarious Nov 14 '10 at 17:09
  • @Omni Yes and that is because `delete` tries to deallocate an invalid pointer, but that is well defined. A pointer to a base class has to point to the beginning of the base class, especially when the base class isn't polymorphic. – Šimon Tóth Nov 14 '10 at 17:11
  • 1
    @Let_Me_Be - Deleting an invalid pointer is not well defined. The only invalid pointer for which it's defined what happens when you delete it is the null pointer. And yes, a pointer to a base class has to point to the beginning of a base class, but it does not have to point to the beginning of the derived class it's part of. To give an obvious case... You can have multiple inheritance without virtual functions you know. – Omnifarious Nov 14 '10 at 17:14
  • @Let_Me_Be: Deallocating an invalid pointer is well-defined?! :-O – Chris Jester-Young Nov 14 '10 at 17:14
  • @Omni First, what will happen when you try to deallocate an invalid pointer is not undefined, but implementation defined. I'm talking about the fact, that what will happen is a deallocation of an invalid pointer and that this will happen is well defined. – Šimon Tóth Nov 14 '10 at 17:18
  • `but it does not have to point to the beginning of the derived class it's part of` What the heck was this supposed to mean? – Šimon Tóth Nov 14 '10 at 17:19
  • @Let_Me_Be - Suppose class `B` is derived from class `A`. Then `B b; A &a = b; if (reinterpret_cast(&a) != reinterpret_cast(&b)) { ::std::cerr << "Yay!\n"; }` may print out `Yay!` or it may not. It's not defined whether it does or not. And it's not implementation defined, like whether or not `char` is a signed type, it's undefined, like accessing beyond the bounds of an array. – Omnifarious Nov 14 '10 at 17:24
  • @Omni Try `static_cast`. `reinterpreted_cast` is not involved in this case. – Šimon Tóth Nov 14 '10 at 17:27
  • @Let_Me_Be - I give up. When I give you an answer, you want me to edit it until it's wrong. – Omnifarious Nov 14 '10 at 17:29
  • @Let_Me_Be - You are wrong. `class A { int joe; }; class AA { char fred; }; class AAA { float barney; }; class B : public AA, public A, public AAA { };`. How can calling `delete a;` be defined in your code if the declarations look like this? – Omnifarious Nov 14 '10 at 18:06
  • @Omni OK, whatever you want. I won't repost all the stuff I already said. – Šimon Tóth Nov 14 '10 at 18:12
  • @Let_Me_be - I created a StackOverflow question for this: http://stackoverflow.com/questions/4178889/is-this-there-a-defined-behavior-for-this-code-that-deletes-a-derived-class-throu - I want to see if you can actually admit making a mistake of any kind. – Omnifarious Nov 14 '10 at 18:20
  • 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 A`s destructor must be virtual. Class A`s destructor being not virtual just can make resources is not released correctly. – lj_enjoylife Nov 15 '10 at 01:15
3

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.

Šimon Tóth
  • 33,420
  • 18
  • 94
  • 135