Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I use dynamic_cast to cast TO a void *?

Tags:

c++

casting

So I was reading the answers to dynamic_cast from "void *" and although you can't cast from a void * to a T * several of the responses point out that it is possible to cast a T * to a void *, but don't give any indication why you'd want to do that.

Is this just a bit of trivia that it's possible, or is there a case where it would make sense? I thought about maybe for readability or to make it clear that we're converting to a void *, but given the purpose of dynamic_cast, it doesn't fit very well to me.

For that matter, is there any reason to do anything other than let T * become void * implicitly? I've seen C-style casts to void * used from time to time for this purpose, I presume just to be explicit (assuming we're not doing something unusual like casting int to a pointer or something).

like image 746
FatalError Avatar asked Feb 28 '12 01:02

FatalError


People also ask

When should I use dynamic_cast?

This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.

What is difference between static_cast and dynamic_cast?

static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.

Why do we use the dynamic cast type conversion?

In C++, dynamic casting is mainly used for safe downcasting at run time. To work on dynamic_cast there must be one virtual function in the base class. A dynamic_cast works only polymorphic base class because it uses this information to decide safe downcasting.


3 Answers

First, when using dynamic_cast<void*>(x) you get a pointer to the first byte of the most derived object. As long as the static type of x is polymorphic.

This can be useful in a handful of scenarios, where the address serves as object identity:

  • you now have a way to fully distinguish pointers to subobjects of the same object from pointers to unrelated subobjects.
  • you can now walk some twisted graphs without visiting the same object several times... which can be used for serialization.

Granted, this is certainly not a daily usage, but in C++ the memory address is a de-facto identifier for objects, so a mechanism to access it from any part of the inheritance hierarchy certainly is useful for those few edge cases.

like image 86
Matthieu M. Avatar answered Nov 14 '22 10:11

Matthieu M.


There is a purpose to this, kinda. It is hinted at in the part of the spec that allows it. From N3337, section 5.2.7, paragraph 7:

If T is “pointer to cv void,” then the result is a pointer to the most derived object pointed to by v.

So a dynamic_cast<void*>(...) is really shorthand for static_cast<void*>(dynamic_cast<MostDerivedType*>(...)). And that would be useful... sort of.

The difficulty in making it useful is that you don't necessarily know what MostDerivedType is. After all, it can be different for each expression. So once you have it as a void*, you don't necessarily have a way to cast it back safely. If you make a guess about MostDerivedType and just static_cast it, and you're wrong, then you're in undefined behavior land. Whereas if you do the dynamic_cast to that type (then static_cast to void*), it will at least return NULL if it isn't of that type.

So no, I would say that it isn't very useful. Not if you want to live within the boundaries of C++ and not rely on potentially undefined behavior.

like image 44
Nicol Bolas Avatar answered Nov 14 '22 11:11

Nicol Bolas


It can be useful when implementing wrappers for operators new and delete. The thing is that operator delete allows us to deallocate memory using pointer to a base of a polymorphic object. In such situation, the wrapper would not know, which object is really being deallocated there (out of all the objects that were allocated by the wrapper before). So we use dynamic_cast< void * >() as unique identity of the object - it casts to the most derived type of a polymorphic object. This allow us to keep track of all the objects currently allocated through this wrapper. Such wrapper can be used for memory allocation tracking and for batch deallocations.

like image 1
Ivorne Avatar answered Nov 14 '22 09:11

Ivorne