2

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?

Sisir
  • 4,584
  • 4
  • 26
  • 37
JeffR
  • 828
  • 1
  • 13
  • 22
  • 8
    `base` is not an instance of `A` so the cast returns nullptr as expected. – Retired Ninja Apr 21 '19 at 08:04
  • 3
    Related: [When should static\_cast, dynamic\_cast, const\_cast and reinterpret\_cast be used?](https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used) – TrebledJ Apr 21 '19 at 08:05
  • @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 Apr 21 '19 at 08:07
  • I don't think this is a duplicate. – n. m. could be an AI Apr 21 '19 at 08:14
  • @JeffR You can't use _`dynamic_cast`_ to change an existing `BASE` instance to an instance of `A`. – πάντα ῥεῖ Apr 21 '19 at 08:17
  • 2
    "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 Apr 21 '19 at 08:17
  • 1
    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 Apr 21 '19 at 08:34
  • "If base was an instance of A, why would I need the cast?" - for example if you had this: `std::vector v; v.push_back(new BASE); v.push_back(new A);` then you could use `dynamic_cast` to determine which of the elements stored in `v` were actually instances of `A` and get to treat them as such. – Jesper Juhl Apr 21 '19 at 09:21
  • Btw; In `BASE(void)` - that `void` to denote an empty argument list is redundant in C++. `BASE()` is fine. – Jesper Juhl Apr 21 '19 at 09:24

1 Answers1

5

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.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243