How to use dynamic_cast - c++

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.

Related

how to cast to "this" type from base to derived class

I want to retrieve the initial type in the base class A because the method encodeMsg() will have tasks that are related to the derived type
#include "stdafx.h"
#include <iostream>
struct base {
};
struct derive : base {
};
class A{
public:
A(){}
virtual void encode() {
encodeMsg(_bStruct);
// here I want to cast base to derive but I don't know how I tried
// static_cast<decltype(this)>(_bStruct) but it seems doesn't work
}
virtual void setStruct(base* bStruct) {
_bStruct = bStruct;
}
private:
virtual void encodeMsg(base* bStruct) = 0;
protected:
base* _bStruct;
};
class B : public A {
public:
B(){}
void encodeMsg(base* bStruct) {
derive* _dStruct = static_cast<derive*>(bStruct);
// ..
// stuff within dervied struct
_bStruct = static_cast<base*>(_dStruct); // turn back to base struct
}
};
int main() {
B b;
base* _bStruct = new derive();
b.setStruct(_bStruct);
b.encode();
return 0;
}
The question makes no sense.
In your code, the only thing you could do with the pointer, if you could create it, is access members known to be in the base class. But you can do that already without the pointer. So what purpose does the pointer serve?
If you want to one thing if it's a derived1 and something else if it's a derived2, then you need to use one piece of code for the derived1 case and one piece of code for the derived2 case.
If you want to do the same thing regardless of what derived type it is, there is no need for the cast you seek. The code in this function will be the same regardless of what the derived type is.
If you want code that only works if the derived type is some specific type, use a dynamic_cast to a pointer to that type and write the specific code. If you want code that works regardless of the derived type, use a pointer to an instance of the base class.
Update:
To access members not in base but in a derived1, use this code:
virtual void encode() {
derived1* d1 = dynamic_cast<derived1*>(bStruct);
if (d1 != nullptr)
{
// here you can access d1->whatever
}
}

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.
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.

Cast function pointers that differs by argument type

Why this is not legal:
class Base
{
public:
Base(){};
virtual ~Base(){};
};
class Derived : public Base{};
void takeDerived(Derived * c){};
// main
void(*ptr)(Base*) = static_cast<void(*)(Base*)>(&takeDerived); // doesn't work
// but this work ok, as well as reinterpret_cast
// void(*ptr)(Base*) = (void(*)(Base*))(&takeDerived);
Derived is a Base. Why can't it be casted in function parameter? For example, I can do this easily even without casting:
void takeBase(Base* c){};
takeBase(new Derived{});
It's just designed to be that way. A Base isn't a Derived. The is-a relationship for class derivation can't be reversed.
The type of a function parameter means "accept", while the type of an object means "fit". Casting the type of a function changes what it accepts. It's dangerous to allow a function to accept whatever isn't what it originally accepts.
Consider this code:
class Base {};
class Derived : public Base {
public:
int t;
void useDerived() {}
};
void useDerived(Derived *d){
d->useDerived();
}
What should happen if a Base object is passed?
Base b;
((void(*)(Base*))useDerived) (&b);
Even worse, what if another derivation of Base is passed?
class AnotherDerived : public Base {
public:
double t;
void useDerived() {}
};
AnotherDerived ad;
((void(*)(Base*))useDerived) (&ad);
Yes, but you're trying to do it the other way around. You cannot do
void takeDerived(Derived *c) { }
...
Base b;
takeDerived(&b);
The function pointer cast you're trying to do would enable these shenanigans; you could do
void (*ptr)(Base*) = takeDerived;
Base b;
ptr(&b); // Oops.
Then things would explode, and that would be bad.

Is it unsafe to store derived object to void*, then cast base object out of it?

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.

Get derived type via base class virtual function

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!