dynamic_cast<> fails but static_cast<> works - c++

In my project I have a scenario like suppose:
1) BaseClass is an interface which derives from a parent class IFlow
2) ChildClass derives from it ie from Base class
3) In childClass Init function I am using dynamic_cast to cast the objet of IFlow to BaseClass which is as shown below:
void ChildClass::init()
{
IFlow* pFlow = someMethod(); //it returns the IFlow object pointer
//this works for static cast but fails for dynamic cast
BaseClass *base = dynamic_cast<BaseClass*>(pFlow) ;
}
In the above code the 2nd line of dynamic _cast returns zero but if the dynamic_cast is changed to static_cast then the code works as expected .
Please advice

dynamic_cast will "not work" in two instances:
You have somehow compiled your code without RTTI. Fix your compiler settings.
The entire purpose of dynamic_cast is to ensure that the cast actually works. Casting from child to parent always works because every child of some type is guaranteed to be that type (the whole "all dogs are animals, but not all animals are dogs" thing). Casting from a parent to a child can fail if the object is not actually that child type. dynamic_cast will return a null pointer if the IFlow you give it is not actually a BaseClass.
Furthermore, your static_cast does not work. It simply returns a value. A value which, if you ever use it, results in undefined behavior. So it only "works" in the sense that it returned a value you could attempt to use.
So one of these two things happened. Which one is up to you to find, since you didn't give us the implementation of someMethod.

A dynamic_cast<> returns null (zero) if the cast is not legal. In this case it's doing what you want: there is a problem somewhere in your inheritance tree. (The static_cast<> "works" only because it's a sledgehammer; it forces the cast at compile time without any knowledge of the type that the pointer will actually have at runtime.)

if it like this?:
class A
{
public:
A(){a = 0;};
virtual ~A(){};
protected:
int a;
};
A *GetAInstance();
class B : public A
{
public:
B() : A() {b = 1;};
virtual ~B(){};
protected:
int b;
};
class C: public B
{
public:
C() : B() {};
~C(){};
void CheckA()
{
A *pA = GetAInstance();
B *pB = dynamic_cast<B*>(pA); --> Here pB is NULL.
B *pB2 = static_cast<B*>(pA);
};
};
A *GetAInstance()
{
A *pA = new A();
return pA;
};
int _tmain(int argc, _TCHAR* argv[])
{
C *pC = new C();
pC->CheckA();
return 0;
}
This is because you are trying to set a parent pointer to its child pointer. In dynamic_cast it thinks it is not safe, so it set the child pointer to NULL, you can see pB above which is NULL. For child class may have more functions/member variables, you call these new functions/member variables would cause run time error. But static_cast doesn't care this, it is only a compiler time check not run time check. static_cast only cares if they have some relation ship. If they have, static_cast convert the pointer even doesn't care run time error. Please run this small sample and check pB2 is not NULL. :)
Hope useful. Thanks! :)

What type is being returned by someMethod()? It needs to be derived from BaseClass to allow dynamic_cast to work. You can't cast downwards if it's not the correct type.
Static cast works at compile time and the compiler will just turn the pointer over.

Related

Safe way to dynamic cast void to a type?

My C++ is a bit rusty and I don't remember everything in the standard.
I have a void*. In one specific function it is either a class that inherits Alpha or one that inherits Beta. Both base classes have virtual functions. However I can't seem to tell which is which
class Alpha {
public:
virtual void Speak() { printf("A"); }
};
class Beta {
public:
virtual void Speak() { printf("B"); }
};
int main(){
//BAD CODE WILL PRINT TWICE
void *p = new Alpha;
Alpha*a = dynamic_cast<Alpha*>((Alpha*)p);
Beta*b = dynamic_cast<Beta*>((Beta*)p);
if(a)
a->Speak();
if(b)
b->Speak();
return 0;
}
How do I figure out which class is which? There are 100's of classes in this codebase that gets converted to void. Most of them inherit 5 base classes however I'm not eager to find out. Is the only solution inheriting from something like class Dummy {public: virtual void NoOp(){}}; and cast to Dummy before using dynamic cast? Is this safe? I'm hoping there's a better solution but I can't think of anything else.
The only thing you can do with a void* pointer is to cast it back to exactly the same type as the pointer that was cast to void* in the first place. The behaviour on doing anything else is undefined.
What you could do in your case is define
class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};
and make this the base class for Alpha and Beta. Then pass a Base* pointer around rather than a void* one, and take your dynamic_casts directly on p.
Note further that if you declared virtual void Speak() = 0; in Base, then your code in main would become simply
int main(){
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}
As a rule of thumb, casts of any kind are undesirable.
The expression Alpha*a = dynamic_cast<Alpha*>((Alpha*)p); first casts p to Alpha* with an explicit c style cast. Then, that resulting Alpha* is passed through dynamic_cast<Alpha*>. Using dynamic_cast<T*> on a T* pointer (a pointer of the same type as you are trying to cast to) will always provide the input pointer. It cannot be used to confirm that the pointer is valid. From cppreference for dynamic_cast<new_type>(expression) :
If the type of expression is exactly new_type or a less cv-qualified version of new_type, the result is the value of expression, with type new_type.
As a result, the code will always compile and run and the type system will not protect you. But the resulting behavior is undefined. In the case of Beta*b = dynamic_cast<Beta*>((Beta*)p); you tell the compiler to trust that p is a Beta* but this is not true. Dereferencing the resulting pointer is undefined behavior and dynamic_cast cannot protect you from this mistake.
If you try to remove the explicit type conversion, you will get a compiler error. dynamic_cast requires a pointer or reference to a complete type, and void is not a complete type. You will have to find a way to track the actual type pointed to yourself and explicitly convert p to that pointer type before using dynamic_cast. Though at that point, if you already know the type to cast to, it may no longer be necessary.
Consider using a common base type instead or maybe using std::variant or std::any if need be.
If you use a C-style cast to convert to Alpha*, similar to a static_cast before using dynamic cast, then the dynamic cast as no effect. here your code runs because the two classes have the same interface but in reality this is undefined behaviour.
Usually, you want to use dynamic cast to upcast/downcast from/to a base class to/from it's derived class.
For example, if we add a base interface, then convert the void * pointer to this base class and then use dynamic cast to attempt Up-casting, the code works as expected and only print once.
#include <stdio.h>
class Speaker {
public:
virtual void Speak() = 0;
};
class Alpha: public Speaker {
public:
virtual void Speak() { printf("A"); }
};
class Beta: public Speaker {
public:
virtual void Speak() { printf("B"); }
};
int main(){
void *p = new Alpha;
// Convert to base type, using static_cast
Speaker *s = static_cast<Speaker *>(p);
// Attempt Upcasts
Alpha*a = dynamic_cast<Alpha*>(s);
Beta*b = dynamic_cast<Beta*>(s);
// See if it worked
if (a)
a->Speak();
if (b)
b->Speak();
return 0;
}
Outputs: A
You must know the type from which the void pointer was converted from. If you don't know the dynamic type, then you must create the void pointer from the pointer to base. If you don't know the type of the pointer which the void pointer was created from, then you cannot use the void pointer.
Given that the void pointer was converted from Alpha*, you can convert it back using a static cast:
auto a_ptr = static_cast<Alpha*>(p);
You can then use dynamic_cast to convert to a derived type.
if(auto d_ptr = dynamic_cast<DerivedAlpha*>(a_ptr)) {
// do stuff with DerivedAlpha
In case the dynamic type isn't DerivedAlpha, the dynamic cast would safely return null. You cannot dynamic cast away from a type hierarchy. Since Alpha and Beta are not related by any inheritance structure, they cannot be dynamically casted mutually.
I feel this could be explained more simply than what is said already.
Basically, casting from a raw void*, none of the "smarts" of dynamic_cast can apply because it has nothing to go on, it just gives you back the same pointer. You need to have some shared parent class type or something as your pointer type (*p) so it knows how to read the memory and determine actual type.
In your case, you are "lucking out" that the memory layout of Alpha and Beta is the same so calling speak on Beta* ends up calling Alpha::speak(). As others said this is UB and if the classes were more different you would likely seg-fault or corrupt the stack.

Parent class using method from child

Is there a way I can use child methods with a parent class pointer:
#include <iostream>
class Parent {
public:
int a;
virtual int ret() {
return a;
}
};
class Child: public Parent {
int b;
public:
int ret() {
return a;
}
int retB() {
return b;
}
};
void main() {
Parent* parent = new Child();
parent->retB();
}
Im using an array of Parent pointers with derived classes as members.
Is there a simple solution to this or should i just rethink my code?
Out of the blue? No.
With certain checks? Yes.
What do I mean by that? Suppose you have a following class hierarchy:
struct Base {};
struct DerOne : Base {};
struct DerTwo : Base {};
Then you create a pointer of Base type to some derived class:
Base* b_ptr = new DerTwo();
It compiles correctly. Now imagine you want to call DerTwo's imaginary method. In your world, it may be ok, but why it's not?
There would have to be some checks, whether or not what b_ptr points to actually implements the method you want to invoke. These checks are not automatically performed. In C++ you don't pay for what you don't need. It'd be pointless to have those kind of checks every time we call any method via a pointer.
So how can you achieve it?
You have to ensure that b_ptr points to something that implements the method you want to invoke. How?
static_cast vs dynamic_cast:
Base class' pointer cannot invoke methods that are not declared in Base class. That's a fact. Done. If you wish to invoke some method from Derived class, you need to change the type of the pointer. How you do that? You either use static_cast<> or dynamic_cast<>. Here you can read more about C++ casts, but for now, I will tl;dr this question and answer for your specific example.
Option #1: You know that type pointed to by b_ptr is of a certain class (let's assume we're talking about DerTwo) and you want to invoke a foo() method declared inside it.
You use static_cast<>. You use it because you know and are certain that there is a specific, derived type object pointed to by a base class pointer. Regarding our example, it'd look like this:
Base* b_ptr = new DerTwo();
DerTwo* der_ptr = static_cast<DerTwo*>(b_ptr);
der_ptr->foo(); // b_ptr and der_ptr point to the same object
Option #2: You don't know the type of the object pointed by b_ptr and want to check if it's safe to call foo().
Suppose that foo() is declared only in DerTwo. Thus, if b_ptr points to DerOne object and you'd want to call foo(), terrible things would happen. You'd call a non-existing method. You have to perform a check, via dynamic_cast<>:
Base* b_ptr = new DerTwo();
DerTwo* der_ptr = dynamic_cast<DerTwo*>(b_ptr);
if(der_ptr != nullptr){
der_ptr->foo(); // b_ptr and der_ptr again point to the same object
} else {
// b_ptr somehow does NOT point to DerTwo object
}
dynamic_cast<> performs a check, whether or not it's argument actually points to the object of specified type. It it does, it returns a pointer of the specified type to the object. If it fails, it returns nullptr, so all you have to do to check if your dynamic casting succeeded, is compare it's result to nullptr.

Call a function of base class casted to derived class

Say that I have the following code, is it safe to use?
Base class:
class B
{
public:
B(bool isDerived = false) : m_isDerived(isDerived) {}
bool isDerived() { return m_isDerived; }
private:
bool m_isDerived;
}
Derived class:
class D : public B
{
public:
D() : B(true) {}
}
Code:
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b); // Cast the base class into a derived class
if (unknown->isDerived()) // Is this allowed?
// unknown is a D and can be used as such
else
// unknown is not a D and can not be used
Can I safely call unknown->isDerived() even though unknown is really a B in this case?
We make the assumption that unknown NEVER contains anything other than a B* or D* and that we NEVER do anything with unknown until isDerived() have been checked on it.
Edit:
Given the questions I will try to explain the reason why I'm trying to do this:
So essentially I have a Windows tree control which of course can't be directly connected to the c++ tree structure I'm using to store my data. So I have to reinterpret_cast my data to a DWORD_PTR that is stored together with each node in the tree control so I have a connection between the two. My tree structure consists of either the base type (a normal node) or the derived type (a node with more info in it that should be handled differently). The pointers to these are reinterpret_cast:ed and put in the tree control.
Now, when I'm stepping through the tree control I want to act on the nodes which are of the derived type, so I want to reinterpret_cast the DWORD_PTR into a derived type. But to be entirely correct I should reinterpret_cast it to a base type first (I guess?), and then downcast it to the derived type if it is a derived type. However I thought I could make it a bit simpler by reinterpret_cast it into a derived type immediately and then check via the function if it really is a derived type. If it wasn't I do nothing more with it. In my mind the base class data in the pointer should be at the same memory location no matter how much derived it is, but I might be wrong which is why I ask here.
I wanted to make the question clearer by not involving Windows in it, but what I want in reality would be something closer to this:
B* b1 = new B();
B* b2 = new D();
DWORD_PTR ptr1 = reinterpret_cast<DWORD_PTR>(b1);
DWORD_PTR ptr2 = reinterpret_cast<DWORD_PTR>(b2);
D* unknown = reinterpret_cast<D*>(ptr1 /* or ptr2 */); // Safe?
unknown->isDerived(); // Safe?
Essentially no matter what I do it's still unsafe at some level as I must reinterpret_cast the data.
Can I safely call unknown->isDerived() even though unknown is really a
B in this case?
First of all, why would you do this? You could just call b->isDerived() and then do the downcasting.
Now, while premature and likely invalid downcast yields an undefined behavior (and should be universally despised) in this case it should work. Neither B nor D have implicit data members that might change the relative offset of m_isDerived and the address of isDerived member function is constant.
So yeah, it should work. If should is good enough for you.
EDIT: You can place a few tests to make sure offsets are same:
#include <cstddef> // for offsetof macro
#include <cassert> // for assert
#define offsetofclass(base, derived) ((static_cast<base*>((derived*)8))-8)
class Test
{
public:
Test()
{
assert(offsetofclass(B, D) == 0);
// you'll need to befriend Test with B & D to make this work
// or make the filed public... or just move these asserts
// to D's constructor
assert(offsetof(B, m_isDerived) == offsetof(D, m_isDerived));
}
};
Test g_test;
This will get executed on startup. I don't think it can be turned into a static assertion (executed and compile time).
Given your
class D : public B
and
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b);
Formally this is Undefined Behavior, but, as long as only B things are accessed there's no technical reason why it should not work. Typically it's done in order to gain access to otherwise inaccessible B things, such as std::stack<T>::c. However there are better ways to do that, including the member function pointer trick.
Regarding
B(bool isDerived = false) : m_isDerived(isDerived) {}
that's very brittle and unsafe.
Instead class B should have a virtual member. Then you can use dynamic_cast and typeid. This is commonly known as RTTI, Run-time Type Information.
However, on the third and gripping hand, the relevant functionality should be made available via class B so that no downcasting is necessary.
As you have pointed out yourself, the only generally correct approach for storing an arbitary hierarchy in a single, opaque pointer is to go via the base class. So, first make your hierarchy:
struct Base { virtual ~Base(){}; /* ... */ };
struct FooDerived : Base { /* ... */ };
struct BarDerived : Base { /* ... */ };
struct ZipDerived : Base { /* ... */ };
You will now exclusively transform between a Base* and whatever raw pointer type you have. Strictly speaking, you can only store pointers in either a void* or a uintptr_t, but let's assume that your DWORD_PTR is wide enough.
If we wrap everything in a function, the upcasting is already taken care of:
void marshal_pointer(Base const * p, DWORD_PTR & dst)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
dst = reinterpret_cast<DWORD_PTR>(p);
}
The return direction is just as easy:
Base * unmarshal_pointer(DWORD_PTR src)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
return reinterpret_cast<Base *>(src);
}
All the actual polymorphic behaviour should be implemented in terms of virtual functions if possible. Manual dynamic_casts should be your last resort (though occasionally they're appropriate):
Base * p = unmarshal_pointer(weird_native_windows_thing);
p->TakeVirtualAction();

Is there a way to return a child* to a base* and evaluate which child* has been returned?

I tried this which didn't work:
void Map::OnLMClick(short xPos, short yPos)
{
SObject* pSObject = pEditWindow->GetSelectedItem();
if (pSObject==SOTile)
{
/* Do */
I tried this as a test:
SObject* EditorWindow::GetSelectedItem()
{
return pSOTile[1]; //pSOTile[1] is a valid pointer, member of EditorWindow
}
SOTile class is a child of base class SObject. So, is it possible to create a Base* to get one of its child's* returned and then have the program react differently depending of what child it returned? If it is the case, how do I then have access to members of it's child that are not members of base?
If your types are polymorphic (i.e. if they have at least one virtual function), you can use dynamic_cast:
Base* pObject = get_object(); // May return a pointer to Derived
Derived* pDerived = dynamic_cast<Derived*>(pObject);
Notice, that dynamic downcasts are sometimes an indicator of bad design. Try to think if a better arrangement of virtual functions in your hierarchy would help.
Without knowing the concrete application domain, it is not possible for me to give more concrete advices.
dynamic_cast operator performs a special checking when a class is polymorhic.
SOTile* pSOTile = dynamic_cast<SOTile*>(pSObject);
if (pSOTile)
{
/* Do */
}
Since SOTile is a pointer to a type that derives from SObject, you should not need to cast at all, since the compiler should be able to automatically resolve an SObject pointer from the derived pointer and then compare the two SObject pointers together (the same way that you can assign a derived pointer to a base pointer without type-casting). Some compilers, like Borland's, support that just fine, eg:
class Base
{
};
class Derived : public Base
{
};
Derived *d = ...;
Base *b = ...;
if (b == d) // <-- compiles fine
However, if for whatever reason your compiler does not allow that, you can manually cast the derived pointer using static_cast (don't use dynamic_cast to cast the base pointer):
if (pSObject == static_cast<SObject*>(SOTile))
If SOTile is not a pointer to a type that derives from SObject, static_cast will fail at compile-time.
I wouldn't recommend to use dynamic_cast. Instead, you can implement that different behavior in different child class. Sometimes called as "template method" pattern

downcasting dynamic_cast with non-polymorphic classes, why doesn't it compile?

I have the following code:
using namespace std;
class BaseOk
{
public:
virtual void ImplementMe()
{
};
};
class DerivedOk : public BaseOk
{
public:
void ImplementMe()
{
}
};
class CBase { };
class CDerived: public CBase { };
int main()
{
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived -> this doesn't compile
// Polymorphic case
BaseOk b2; BaseOk* pb2;
DerivedOk d2; DerivedOk* pd2;
pb2 = dynamic_cast<BaseOk*>(&d2); // ok: derived-to-base
pd2 = dynamic_cast<DerivedOk*>(&b2); // wrong: base-to-derived -> this returns a NULL pointer
}
The line with the pointer "pd" performs a downcast and I agree that it should fail because the result is a totally different object.
My question is: why doesn't the dynamic_cast in that line compile at all instead of just returning a NULL pointer?
I'm using MSVC2012 compiler
Why doesn't the dynamic_cast in that line compile at all instead of
just returning a NULL pointer?
Consider this as a feature/facility rather than a limitation.
dynamic_cast is a mechanism where we would find the RTTI (run-time type information) of an object based on the pointer/reference.
Now suppose if a class is not at all polymorphic (i.e. doesn't contain any virtual method), then definitely the dynamic_cast will always fail.
Which means you don't have to use the dynamic_cast where there is a 0 probability of passing. Why should you waste machine cycles on the thing which is known at compile time? That's why compiler provides you the facility straight away.
There is another hidden advantage of this. Suppose you are using dynamic_cast with references, if it fails then an exception is thrown. Would anyone want to handle an exception for something which is already known at compile time!
Using dynamic_cast on a pointer to a non-polymorphic type is an error. That's a diagnosable rule, so you should get a compile-time error.
Using it on a pointer to a polymorphic type which is not convertible to the target type is not an error, and in any case is not generally detectable when compiling. It has well-defined behaviour, giving a null pointer.