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.
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
When you convert a pointer to an object type into a pointer to void, the only valid conversion for that void pointer is back to its original type. You can't use dynamic_cast on a pointer to void because void is not a polymorphic type, so you do it with a static_cast. Like this:
BASE *pbase = new DERIVED;
void *vbase = pbase; // Ok; implicit conversion to void*
BASE *pbase1 = static_cast<BASE*>(vbase); // the cast is required
Once you've gotten back the pointer to BASE, of course, you can use dynamic_cast to convert it to a pointer to the derived type:
DERIVED *pder = dynamic_cast<DERIVED*>(pbase1);
You cannot use dynamic_cast on a void *.
From the specification, for dynamic_cast<T>(v):
If T is a pointer type, v shall be a prvalue of a pointer to complete class type, and the result is a prvalue of type T. ...
What you should do is to let all your classes derive from the same polymorphic base class (which has at least one virtual function) BASE, and use BASE * instead of void *.
Your generic linked list should be like this:
class Node
{
Node* next;
void* vdata;
}
That's the only data structure strictly required, but you might want a circular list, or a base node to keep track of the end of the list, or a doubly-linked list.
Caller passes you a void*, you create a new node, set "vdata" and add the node to your list.
Related
I am trying to use dynamic_cast - with no success. I have a BASE class, and a class A derived from BASE. I want to have a pointer to a BASE class object which I later want to cast to class A. I clearly am not doing this correctly. The following code compiles:
#include <cstdio>
class BASE {
private:
int i;
public:
BASE(void) {i = 1; }
virtual ~BASE(){}
virtual void id() { printf("CLASS BASE\n"); }
};
class A : public BASE {
public:
A(void): BASE() {}
A(const BASE & base) : BASE(base) {}
A& operator = (const BASE & base) { static_cast<BASE&>(*this) = base; return *this; }
void id() override { printf("CLASS A\n"); };
};
int main() {
BASE* base = new BASE();
base->id();
A* a = new A(*base);
a->id();
A* anotherA = dynamic_cast<A*>(base);
if(!anotherA)
printf("anotherA is NULL\n");
else
anotherA->id();
}
but running it gives:
CLASS BASE
CLASS A
anotherA is NULL
I am sure I'm missing something very basic, but I keep staring at the code and can't see what I'm doing wrong. Any help would be very much appreciated.
I have looked at
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
but don't understand why dynamic_cast doesn't work - isn't this just a simple downcast?
I am sure I'm missing something very basic
You do.
When you have an object of type A, and a pointer to that object of type A*, the pointer can be converted to type BASE*. This conversion partially forgets information about the type.
Now given a pointer of type BASE*, if this pointer actually points to an A object (that is, it was converted from type A* at some point), you can recall forgotten type information by casting the pointer back to type A*.
If your pointer does not point to an object of type A to begin with, then nothing was forgotten and there is nothing to recall.
To avoid an X Y situation , I'm trying to validate if a void* pointer cast is valid.
In order to solve this I wanted to use the properties of dynamic_cast.
Given the following code:
class A
{
virtual void foo(){}
};
class B
{
virtual void bar(){}
};
void* createA() { return new A();}
void* createB() { return new B();}
int main()
{
A* ptr =reinterpret_cast<A*>(createA());
A* ptr2 = reinterpret_cast<A*> (createB());
ptr = dynamic_cast<A*>(ptr); // not NULL as expected
ptr2 = dynamic_cast<A*> (ptr2); // was expecting NULL, however it's a valid pointer
}
Wasn't dynamic_cast supposed to fail with NULL if the RTTI isn't as the expected type ?
The usual way to solve such problems is to give A and B a common tag base class/interface. void* doesn't preserve any type information. Also reinterpret_cast<> would simply override any potentially present type information.
You can do something like this:
class Base {
public:
virtual ~Base() {}
};
class A : public Base
{
virtual void foo(){}
};
class B : public Base
{
virtual void bar(){}
};
Base* createA() { return new A();}
Base* createB() { return new B();}
int main()
{
Base* ptr = createA();
Base* ptr2 = createB();
ptr = dynamic_cast<A*>(ptr); // not NULL as expected
ptr2 = dynamic_cast<A*> (ptr2); // NULL pointer now
}
dynamic_cast can not be used to inspect whether a pointer to arbitrary memory address points to an object of particular kind. dynamic_cast will perform conversion by inspecting RTTI of the object being pointed to only at scenarios when type of this object may be in the inheritance chain of the type being cast to. In your example casting B * to A * will always produce a nullptr even if B * actually points to A:
A * a_ptr = dynamic_cast<A*>(reinterpret_cast< B* >(createA()));
assert(nullptr == a_ptr);
Moreover, you are trying to cast A * to a A * which basically results in noop:
5.2.7 Dynamic cast [expr.dynamic.cast]
3 If the type of v is the same as T , or it is the same as T except that the class object type in T is more cv-qualified than the class object type in v, the result is v (converted if necessary).
The following code works (on ideone, Borland BCB 6 and gcc)
#include <stdio.h>
class Base {
private:
Base **BPtr;
public:
Base(void *Ptr) {
BPtr = (Base **)Ptr;
*BPtr = this;
}
virtual ~Base() {
if(BPtr) *BPtr = NULL;
printf("Base aufgelöst\n");
}
};
class Child : public Base {
public:
Child(void *Var) : Base(Var) {}
~Child() {
printf("Child aufgelöst\n");
}
};
int main() {
Child *Ptr = NULL;
new Child(&Ptr);
printf("Childptr: %p\n", Ptr);
delete Ptr;
printf("Childptr: %p\n", Ptr);
return 0;
}
The output of above program is:
Childptr: 0x9cc0008
Child aufgelöst
Base aufgelöst
Childptr: (nil)
which is exactly what I expected and want.
My question is simple: Is this actually safe or does it only seem to work? Because it does feel a little bit hacky to first implicitly cast a Pointer of type Child to a void * and then cast it to a Base ** or are there any obvious (or hidden) problems with this?
Thank you very much.
Edit:
Since there seemed to a bit of a misunderstanding regarding my intention:
The sole purpose of this 'hack' is to NULL the variable in question, once the object gets destroyed to protect myself against accidentally forgetting to NULL the variable manually and possibly accessing invalid memory later on.
The variable must and will not be used to access any other functionality of the classes.
However, what I also tried (and worked) before was the following:
void FreeFunc(void *Ptr) {
if(Ptr) {
Base **BPtr = (Base **)Ptr;
delete *Ptr; //Calls Destructors
*Ptr = NULL;
}
}
Which appears to be even worse from the replies I had been getting on here so far?
Casting a Child * to a Base * is safe. Casting a Child** to a Base** is not because those are unrelated. The problem with doing this is that if I cast to void * then to Base**, I can now assign a Base * to a pointer of type Derived *, like this:
#include <iostream>
class Base
{
public:
virtual void Foo() { std::cout << "Base::Foo" << std::endl; }
};
class Child : public Base
{
public:
virtual void Foo() { std::cout << "Child::Foo" << std::endl; }
virtual void Bar() { std::cout << "Child::Bar" << std::endl; }
};
void main()
{
Child *d = new Child();
Base *b = d;
Child **d2 = &d;
Base **b2 = (Base **)(void *)d2; // Force it
*b2 = new Base(); // Whoops! Child *d now points to an instance of Base *
d->Bar();
}
You can check, if the the void* pointer from your function can be cast to the Base* with the dynamic_cast<Child*> c++ function and check if the result is equal to 0 (no cast possible).
But a dynamic_cast is not very efficient and the cast ist very slow.
What would happen if:
Any of the Base functions call some other member func (either of
Base or of Child? Virtual or non-virtual.
And what is the guarantee that the void *points to the Child* ?
For ex: nothing prevents us to write in main:
void *pv;
new Child(pv);
These should point to say that such type cast is not guaranteed.
If we really need typecasting base<->derived, RTTI is the mechanism.
Also see wiki for RTTI:
Converting from Base* to Derived* and vice versa can change the bits in the value -- you cannot safely convert from Base** to Derived**. The same in theory can be true for void*, but in practice is less likely.
Storing a void** is more likely to work than storing a Base** marginally. Still undefined.
Converting back and forth from void* is only valid if you go to and from the exact same type.
The most common case where the address changes when you simply change the type is with multiple inheritance:
struct Base1 { char x; };
struct Base2 { char y; };
struct Derived: Base1, Base2 {};
In this case, Derived* d points at the same address as Base1, but Base2 is after that. A pointer to the Base2 subobject of Derived will have a different binary address.
In C++, there are a limited number of situations where a pointer-to-A can be reinterpreted as a pointer-to-B. These are when the two are layout compatible. Layout compatible only occurs when the types in question are plain old data/standard layout, and when basically one class is a prefix of the other. Most other situation, the compiler is pretty much free to rearrange where things live.
At best you can delve into your particular implementation's object layout, and hope you didn't miss anything. In practice, it is often better to use something like a type-erased destroyer rather than risk the problem: store both the void** and a pointer-to-function that knows what type it was cast from, and casts it back to that.
struct cleanup_stuff {
void* pvoid;
void(*pfunc)(void*);
void operator()() const {
pfunc( pvoid );
}
};
template<class T>
cleanup_stuff clear_pointer( T** ptr ) {
return {
static_cast<void*>(ptr),
[](void* p){
T** ptr = static_cast<T**>(p);
*ptr = nullptr;
}
};
}
here we have our cleanup_stuff struct that stores a void* and an operation on said void*. Our clear_pointer takes a pointer-to-pointer, and creates a cleanup_stuff that stores the clearing of said pointer at a later point in time.
Store a cleanup_stuff in your Base, and have it take its pointer as a template T**. In the destructor, execute the cleanup_stuff. This has an extra pointer overhead over your solution, and does not execute undefined behavior.
For example:
class Base1 {};
class Base2 {};
class Derived: publid Base1, public Base2 {};
// object is stored on a void* slot
void* void_slot = new Derived();
// ... many decades after ...
//object is fetched from the void* slot
Base2* obj = (Base2*) void_slot;
obj->some_base2_method();
I think it is probably unsafe. Does dynamic_cast<> solve this issue?
Base2* obj = dynamic_cast<Base2*> void_slot;
More backgrounds:
I'm working on calling C++ library from Perl. When you construct an C++ object, it is stored in the integer slot of a Perl value (the IV value of a SV), which is like a void*; and when you call methods, the object pointer is cast from IV, and the corresponding C++ method is called using the object pointer. Thus I guess it could be problematic, as the pointer to base type can be different with the pointer to derived type, especially when there are multiple inheritance.
I've posted a similar question on PerlMonks, but did not get much response from there. So I ask it here, from the aspect of C++.
Yes it is unsafe, but will probably cause no errors in your example due to the empty base optimization. Consider instead the following example:
class Base1 { int b1; };
class Base2 { int b2; };
class Derived : public Base1, public Base2 { int d; };
The memory layout for an object of type Derived will probably look like this:
0123456789AB
[b1][b2][ d]
^ begin of Derived
^ begin of Base1
^ begin of Base2
Now, a pointer to Derived and to Base1 will have the same numerical value, but one to Base2 will be different. To change the numerical value appropriately, the compiler has to know that you are converting a Derived* to a Base2*. This is not possible when casting it to void* in between, since the value of the void* could just as well have come from a Base2*.
In fact, a conversion sequence like static_cast<T*>(static_cast<void*>(x)) is exactly how reinterpret_cast<T*>(x) is defined. And you would not assume that reinterpret_cast is safe to randomly use an arbitrary types - would you?
What about dynamic_cast?
While one might believe that dynamic_cast might help here, it is in fact not even applicable! Since dynamic_cast is supposed to use run time type information to guarantee that a cast is possible, its target needs to be a pointer (or reference) to a class type with at least one virtual member. In this case, the target is not even a pointer to a complete type, but to void.
How to deal with the conundrum?
No matter what you do afterwards you must retrieve the same type of pointer that you stored (with a sole exception for interpreting your object as a char array). The obvious solution would be, to either always store a pointer to a common base class like
void* void_slot = static_cast<CommonBase*>(input);
CommonBase* output = static_cast<CommonBase*>(void_slot);
or to use an intermediate class that knows which kind of pointer you are talking about
struct Slotty {
enum class type_t {
Base1,
Base2,
Derived
} type;
void* ptr;
Slotty(Base1* ptr) : type(type_t::Base1), ptr(ptr) { }
Slotty(Base2* ptr) : type(type_t::Base2), ptr(ptr) { }
Slotty(Derived* ptr) : type(type_t::Derived), ptr(ptr) { }
};
void* void_slot = static_cast<void*>(new Slotty(input));
Slotty* temp = static_cast<Slotty*>(void_slot);
switch(Slotty.type) {
case Slotty::type_t::Base1:
/* do sth with */ static_cast<Base1*>(temp.ptr);
break;
case Slotty::type_t::Base2:
/* do sth with */ static_cast<Base2*>(temp.ptr);
break;
case Slotty::type_t::Derived:
/* do sth with */ static_cast<Derived*>(temp.ptr);
break;
}
If you have complete control over your classes, just create a single virtual root base. Cast to that first before you cast to void *, then cast back to that first. Then you can use dynamic_cast to cast to whatever derived type you want:
struct Root {
virtual ~Root() {}
};
struct Base1 : virtual public Root { };
struct Base2 : virtual public Root { };
struct Derived1 : public Base1, public Base2 { };
struct Derived2 : public Derived1 { };
int main() {
Derived1 *d1 = new Derived1;
Derived2 *d2 = new Derived2;
void *vp = static_cast<Root *>(d1);
Derived1 *d11 = dynamic_cast<Derived1 *>(static_cast<Root *>(vp));
vp = static_cast<Root *>(d2);
Derived2 *d22 = dynamic_cast<Derived2 *>(static_cast<Root *>(vp));
delete d1;
delete d2;
}
EDIT: Apparently the classes must be polymorphic and you must use dynamic_cast, so put a trivial virtual destructor in Root.
I am trying to get the derived type of an object via a base class virtual function. I have written this, which does not compile:
struct base {
virtual base& get_this() {
return *this;
}
};
struct derived : base {
virtual derived& get_this() override {
return *this;
}
void fn();
};
int main () {
base* pd = new derived();
derived& x = pd->get_this(); /*ERROR*/
x.fn();
return 0;
}
... giving me an error that: I cannot initialize a derived& from a base. Since get_this is virtual, why does pd->get_this() return a base& instead of a derived&? Thanks in advance!
EDIT:
Thanks everyone for their useful answers and apologies for my late reply. I should have specified in the original post that I am also interested in a solution to my problem rather than just figuring out why the above does not compile. My main problem is that fn is unique to the derived class and cannot be called via the base class. Using casts sure solves the problem but I hate writing code with if else constructs just to get the right type (also Scott Meyers advise against casts :)) . The answers seem to indicate that casts are the way to go, which in a way is at least reassuring that I am not neglecting a more 'elegant' solution to my problem. Thanks again!
C++ covariant return types support will only work, as long you already know the derived type. To downcast a base class to a possibly derived class, simply use dynamic_cast<derived>(base_ref) to determine if base_ref matches the actual derived type:
int main () {
base* pd = new derived();
derived& x = dynamic_cast<derived&>(*pd); // Will throw an exception if pd
// isn't a 'derived'
x.fn();
return 0;
}
Or alternatively:
int main () {
base* pd = new derived();
derived* x = dynamic_cast<derived*>(pd); // Will return nullptr if pd isn't
// a 'derived'
if(x) {
x->fn();
}
else {
// dynamic_cast<derived*> failed ...
}
return 0;
}
c++ supports covariant return types for derived classes, but as the other answers describe you cannot get it via calling the base class (pd->get_this()) here.
You might also consider static polymorphism to check type compliance at compile time, if you can't use RTTI, exception handling or want tight type binding (without vtable overhead).
The static type of pd is base *. Thus, when the compiler looks for the member function get_this(), it finds only base::get_this(). The return type of base::get_this() is base&, which is not convertible to derived&. Hence the error.
I would like to add to Novelocrat's answer by referring you to section 10.3, paragraph 8 of the working draft C++ standard (click here) which explains in which case the returned pointer's static type is Derived* as opposed to Base*. Basically, if you would have called get_this() through a pointer to the dervied class then you would have gotten the right type with no compiler error.
Here is a quote from the standard along with an example (also from the standard):
If the return type of D::f differs from the return type of B::f, the
class type in the return type of D::f shall be complete at the point
of declaration of D::f or shall be the class type D. When the
overriding function is called as the final overrider of the overridden
function, its result is converted to the type returned by the
(statically chosen) overridden function (5.2.2). [Example:
class B { };
class D : private B { friend class Derived; };
struct Base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
virtual B* vf4();
virtual B* vf5();
void f();
};
struct No_good : public Base {
D* vf4(); // error: B (base class of D) inaccessible
};
class A;
struct Derived : public Base {
void vf1(); // virtual and overrides Base::vf1()
void vf2(int); // not virtual, hides Base::vf2()
char vf3(); // error: invalid difference in return type only
D* vf4(); // OK: returns pointer to derived class
A* vf5(); // error: returns pointer to incomplete class
void f();
};
void g() {
Derived d;
Base* bp = &d; // standard conversion:
// Derived* to Base*
bp->vf1(); // calls Derived::vf1()
bp->vf2(); // calls Base::vf2()
bp->f(); // calls Base::f() (not virtual)
B* p = bp->vf4(); // calls Derived::pf() and converts the
// result to B*
Derived* dp = &d;
D* q = dp->vf4(); // calls Derived::pf() and does not
// convert the result to B*
dp->vf2(); // ill-formed: argument mismatch
}
C++ supports covariant return type.
What it means is that when you call get_this() on a derived object through a base pointer it is the implementation of derived that is going to be called.
However this does not mean that calling base::get_this will give you a derived&. The return type of base::get_this is base&. if you want to get a derived object you will have to call get_this through a derived pointer (or downcast your base& to a derived&). Note that this is how return type covariance work in Java, C++, D...
base* pbase = new base();
base* pderived = new derived();
derived* pderived2 = new derived();
base& a = pbase->get_this(); // call implementation in base, return base&
base& b = pderived->get_this(); // call implementation in derived, return base&
derived& c = pderived2->get_this(); // call implementation in derived, return derived&
I found a simple solution, but if is possible, I would the masters to evaluate:
class base{
type = 1;
virtual int getType() final {
return type;
}
}
class derived1 : public base {
derived1(){
type = 2;
}
}
This way, you can call the method 'int getType()' of any of derived classes. As the type is set on the constructor, there is no risk of misbehaviour.
To enhance the usability, i've created a predefined 'types'.
I'm using, but I don't know if is MacGyvery!