Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I dynamically cast from a void * pointer generically?

class BASE {
public:
    virtual ~BASE() {}
    void lamp() {
        cout << "\nBASE CLASS";
    }
};

class DERIVED : public BASE {
public:
    void fun();
};

void DERIVED::fun() {
    cout << "\nDERIVED CLASS!";
}

int main() {

    BASE * pbase = new DERIVED; //BASE CLASS POINTER
    void * vbase = pbase;       //VOID POINTER TAKING BASE POINTER 
    DERIVED * pder;             //DERIVED CLASS POINTER

    //pder = static_cast<DERIVED *>(vbase);  //THIS WORKS
    pder = dynamic_cast<DERIVED *>(vbase);   //THIS DOESN'T
    pder->lamp();
    pder->fun();

    return 0;
}

Whenever I try to dynamically cast the void* pointer to the derived class pointer, I get the following error:

cannot dynamic_cast 'vbase' (of type 'void*') to type 'class DERIVED*' (source is not a pointer to class)

I've searched StackOverflow and followed advice by implementing a virtual function in the base class to avoid the error. What am I doing wrong? Is this possible at all?

My overall intention is to cast ANY incoming Object type into a Derived class type using a void* pointer. I hope you understand what I mean.

For example:

void dynamicCast(void * vptr)
{
    BASE * pbase = new DERIVED;
    DERIVED * pder;

    pder = dynamic_cast<DERIVED *>(vbase);
}

I should be able to pass any type of pointer to the dynamicCast function and it should be converted to the derived class pointer.

like image 588
Vignesh Gunasekaran Avatar asked Mar 09 '23 05:03

Vignesh Gunasekaran


1 Answers

I think there is a design or/and comprehension problem

As explained you can not dynamic_cast from a void*.

Why? Because dynamic_cast needs some Run-Time Type Information (RTTI) to do the cast (see this link for further details). From void* alone, the C++ code has no chance to know where this information is. The minimum is to use a pointer to an object having such RTTI information.

This information is created and bounded to any class having at least one virtual method. If there is no virtual method this information is not included. That is the reason why this does not work:

struct A
{
};

struct B : A
{
};

int main()
{
  B  b;
  A *a = &b;

  dynamic_cast<B *>(a);  // YOUR COMPILE TIME ERROR
}

A fix is to add a virtual method to A. Here I have added a virtual destructor as this is generally a good thing

struct A
{
   virtual ~A() = default;
};

struct B : A
{
};

int main()
{
  B  b;
  A *a = &b;

  dynamic_cast<B *>(a);  // OK
}

Also note that dynamic_cast allows you to check that the conversion was legal.

For instance we can add a C class and check:

struct C 
{
};

int main()
{
  B  b;
  A *a = &b;

  assert(dynamic_cast<B *>(a)!=nullptr); // OK
  assert(dynamic_cast<C *>(a)==nullptr); // OK can not cast A to C 
}

This kind of run-time operations are not free. If you search for maximum speed to can use this trick:

assert(dynamic_cast<B *>(a)!=nullptr);
B* b=static_cast<B*>(a);

In debug mode you will check if everything is ok and in release mode with the -DNDEBUG flag to remove the assert you will only use the static_cast

like image 143
Picaud Vincent Avatar answered Mar 10 '23 19:03

Picaud Vincent