Wednesday, April 23, 2008

Virtual destructors (What? When? Why?)

There are some questions regarding virtual destructor that I am asked very frequently. Answers to all these questions are similar so I am making a common note on it.

• What is the use of virtual destructor?
• When to make base class destructor virtual?
• Is there any overhead for virtual destructor?
• Why don’t we make all the destructor virtual?
• Will the delete operator be overridden?
• Will the delete[] operator be overridden?



What is the use of virtual destructor?

The virtual destructor comes into play when the class is a base class. If the derived class object is deleted using a base class pointer the necessary destruction of the derived class would not happen if only base class destructor is called. To simplify, if the base class destructor is not virtual and if we try to delete the derived class object using base class pointer the derived class destructor will not be called. It’s known that the destruction is done from derived to base; hence if the derived class destructor is called it will call the base class destructor and the proper destruction of the object will be happening. Altogether by making the base class destructor virtual we are making destructor to be capable of overriding.


When to make base class destructor virtual?

Make the destructor of the class virtual if the class has any virtual function. It should probably save because of 2 reasons.

1. Most of the real world base classes will have at least one virtual function.
2. In the real world problems if there is no virtual function in the base class there is no specific advantage in using base class pointer.

Is there any overhead for virtual destructor?

The per-object-space-cost will be nothing because we only make our destructor private when there is at least one virtual method in the base class. When the first virtual method in the class is made; the per-object-space-cost will be paid off and this makes it costless to make the destructor virtual.

Why don’t we make all the destructor virtual?

If there is no virtual function in the base class and you make the destructor virtual it increases the per-object-space-cost for no added advantage. It is safe not to make the destructor if you class,

1. is not a base class
2. or is not having any virtual function

Will the delete operator be overridden?

Yea, the standards state the delete operator will be overridden and the derived class delete operator will be used for the destruction of derived class.


Will the delete[] operator be overridden?

NO, the standards explicitly states the delete[](deleting array of objects) operator will not be overridden and the operator corresponding to the type of pointer will be used for deleting.

For better understanding on delete and delete[] operator with virtual destruction please read the post Virtual Destructor delete and delete[]

Friday, April 11, 2008

The development of NULL - A history

Introduction

Null pointer is a stuff which have had changes and advancement through out the development of C and C++. All the implementation had its own draw backs and now a perfect design is about to arrive in C++0x. Let us analyze the NULL pointer in C, C++ and C++0x.


K&R style(C Style)

A NULL pointer is a constant expression which evaluates to either 0 or ((void*) 0). There are machines which use different internal representations for pointers to different type. In such cases by standard it is always guaranteed a 0 cast to void* will be assignable to every pointer. For example if you assign a ((void*) 0) to a pointer of FILE type it is guaranteed to be initialized to a null pointer without any error.


C++ style(C++98)

A null pointer constant is an integral constant expression rvalue of an integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of a pointer. So the macro NULL is equivalent to an integer 0 and therefore it is better to avoid NULL macro by directly using a 0.


C++0x style

In all the standards till now the constant 0 had double roles of constant integer 0 and null pointer. This behavior existed throughout the development of C and C++. In C the NULL is a macro which assigns to either 0 or ((void*) 0). But in C++ NULL is always a special case represented as 0. But even using a 0 have its own drawback while overloading. For example we have two declarations,

void foo( char* p );
void foo( int p );


and then call foo(NULL). This will call the integer overload of foo where a programmer may normally intend to call char overload with a null pointer.

To get rid of this issue the new standards will include an additional keyword ‘nullptr’ which would only be assignable to pointer types and comparable to pointer types. The existing 0 will have to suffer the double role again to have backward compatibility. But sooner or later C++ committee would declare deprecated usage of 0 and NULL as null pointers, and eventually avoid this double role.