2
votes

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?

1
base is not an instance of A so the cast returns nullptr as expected. - Retired Ninja
@RetiredNinja If base was an instance of A, why would I need the cast? I want to effectively treat base as though it was an object of class A. Is casting base to A not what I need to do? - JeffR
"I want to effectively treat base [which is NOT an A] as though it was an object of class A." That's not what dynamic_cast will do. You can use reinterpret_cast. You'll get undefined behavior, and if you are lucky your application will crash. If you are unlucky, your application may appear to work. - Eljay
Let's say you have another class B derived from BASE. You have a container of BASE* and a mixture of both A and B instances. dynamic_cast can tell you if a particular BASE* points to an instance of A rather than an instance of B. It's usually a code smell if you need to use it for that purpose though as if you can't operate on both A and B instances through the base then maybe they shouldn't be derived from it. - Retired Ninja

1 Answers

5
votes

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.