2
votes

Consider this code:

class A {
  public:
    void fun() {}
};

class B : public A {
  public:
    void fun() {}
};

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

    delete p;
}

Classes A and B are not polymorphic, and neither class declares a destructor. If I compile this code with g++ -Wall, the GCC compiler happily compiles the code.

But if I add virtual to void fun() in A, the compiler issues this warning: "deleting object of polymorphic class type ‘A’ which has non-virtual destructor might cause undefined behavior".

I'm quite aware of the dangers of using non-virtual destructors. But the code above makes me wonder about two things:

  1. Why do I need to write an empty virtual destructor in the base class when I'm not using destructors at all?
  2. Why is the empty virtual destructor not required if the base class contains no other virtual functions?

EDIT

It appears that I need to clarify the thing that bothers me:

The above code declares no destructors.

If I declare a virtual function, the compiler complains about the missing virtual destructor. My conclusion: If the class is polymorphic, I need to write a virtual destructor if delete p is to work correctly.

But if I declare no virtual function (as in the initial example above), the compiler does not complain about a missing virtual destructor. My conclusion: If the class is not polymorphic, I do not need to write a virtual desctructor, and delete p will work correctly anyway.

But that last conclusion sounds intuitively wrong to me. Is it wrong? Should the compiler have complained in both cases?

3
Both questions assert completely incorrect premises, which makes this awkward to answer. The code at hand should simply be written as B *p = new B; and everything would be well.Kerrek SB
I don't see empty virtual destructor in your code.Nawaz
@oz1cz - Why do I need to write an empty virtual destructor in the base class when I'm not using destructors at all? All classes have destructors.PaulMcKenzie
@Kerrek: A *p = new B; delete p; is perfectly legal. The question is does it work for non-polymorphic classes? The compiler warns if the class is polymorphic, but not if it is non-polymorphic. Why?oz1cz
@Nawaz: Of course you don't. I didn't write any, and the compiler complains about me not writing any. However, the compiler only complains if the class is polymorphic. Why?oz1cz

3 Answers

1
votes

Following up on PaulMcKenzie's and KerrekSB's comments, here is the answer to the two questions in the original post:

  1. The class always has a destructor, even when the programmer doesn't explicitly write one. It is necessary to declare an empty virtual destructor in order to prevent the system from automatically generating a non-virtual one.
  2. In the sample code provided, you do need a virtual destructor, even when there is no other virtual function in the class. The fact that GCC doesn't complain in this case is probably a bug in the compiler (or at least a shortcoming).

The background for this is found in §5.3.5 of the C++11 standard, which says, "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." (Italics mine.)

0
votes

You are making an upcasting, in other words: a polymorphic use of the class B. If the class A has not virtual members, the compiler does not generate VTABLE for class A and it is not require a virtual destructor (note that your upcasting has no sense without polymorphism use). While if the class A declares virtual members, a VTABLE is generated by compiler, in this case you should provide a virtual destructor.

0
votes

If your want polymorphic behaviour you need to define at least one virtual function in order compiler should generate v-table for your class.

Because C++ class contains two special functions (constructor and destructor) which used for every object it a good choice to make destructor virtual.

  1. When you write delete p you really call a destructor for object associated with pointer p. If you not declare a destructor as virtual you've get error prone code.

  2. Before your declare at least one of member function as virtual compiler did not expect that you intend using your class as polymorphic. In C++ phylosophy: "You should not pay for functionallity that you will never use". E.g. in simple case destructor should not be virtual.