Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there practical uses for dynamic-casting to void pointer?

In C++, the T q = dynamic_cast<T>(p); construction performs a runtime cast of a pointer p to some other pointer type T that must appear in the inheritance hierarchy of the dynamic type of *p in order to succeed. That is all fine and well.

However, it is also possible to perform dynamic_cast<void*>(p), which will simply return a pointer to the "most derived object" (see 5.2.7::7 in C++11). I understand that this feature probably comes out for free in the implementation of the dynamic cast, but is it useful in practice? After all, its return type is at best void*, so what good is this?

like image 374
Kerrek SB Avatar asked Nov 14 '11 15:11

Kerrek SB


People also ask

When should I use dynamic pointer cast?

In C++, dynamic casting is, primarily, used to safely downcast; i.e., cast a base class pointer (or reference) to a derived class pointer (or reference). It can also be used for upcasting; i.e., casting a derived class pointer (or reference) to a base class pointer (or reference).

What is dynamic casting used for?

Dynamic Cast: A cast is an operator that converts data from one type to another type. 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.

What is one reason you would use a void pointer?

A void pointer can be really useful if the programmer is not sure about the data type of data inputted by the end user. In such a case the programmer can use a void pointer to point to the location of the unknown data type.

Why do we use the dynamic cast type conversion?

Why we use the “dynamic_cast” type conversion? Explanation: It is used to check that operators and operands are compatible after conversion.


2 Answers

The dynamic_cast<void*>() can indeed be used to check for identity, even if dealing with multiple inheritance.

Try this code:

#include <iostream>  class B { public:     virtual ~B() {} };  class D1 : public B { };  class D2 : public B { };  class DD : public D1, public D2 { };  namespace {     bool eq(B* b1, B* b2) {         return b1 == b2;     }      bool eqdc(B* b1, B *b2) {         return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);     } };  int main() {     DD *dd = new DD();     D1 *d1 = dynamic_cast<D1*>(dd);     D2 *d2 = dynamic_cast<D2*>(dd);      std::cout << "eq: " << eq(d1, d2) << ", eqdc: " << eqdc(d1, d2) << "\n";     return 0; } 

Output:

eq: 0, eqdc: 1 
like image 127
mitchnull Avatar answered Oct 08 '22 05:10

mitchnull


Bear in mind that C++ lets you do things the old C way.

Suppose I have some API in which I'm forced to smuggle an object pointer through the type void*, but where the callback it's eventually passed to will know its dynamic type:

struct BaseClass {     typedef void(*callback_type)(void*);     virtual callback_type get_callback(void) = 0;     virtual ~BaseClass() {} };  struct ActualType: BaseClass {     callback_type get_callback(void) { return my_callback; }      static void my_callback(void *p) {         ActualType *self = static_cast<ActualType*>(p);         ...     } };  void register_callback(BaseClass *p) {    // service.register_listener(p->get_callback(), p); // WRONG!    service.register_listener(p->get_callback(), dynamic_cast<void*>(p)); } 

The WRONG! code is wrong because it fails in the presence of multiple inheritance (and isn't guaranteed to work in the absence, either).

Of course, the API isn't very C++-style, and even the "right" code can go wrong if I inherit from ActualType. So I wouldn't claim that this is a brilliant use of dynamic_cast<void*>, but it's a use.

like image 27
Steve Jessop Avatar answered Oct 08 '22 05:10

Steve Jessop