-2

While reviewing an inherited project which is to port from an old version of Visual Studio (6) to a new version (2017), we stumbled across this run time error, in that we were getting an unexpected NULL after using dynamic_cast<>() on a base class. Here is a representative sample:

Given this code:

class a { public: a() {}; virtual ~a() {}; };

class b :public a { public: b() {};  virtual ~b() {}; };

class c : public b { public: c() {};  virtual ~c() {}; };

int main()
{
    a *a_ = new b();
    b *b_ = new c();
    c *c_1 = dynamic_cast<c*>(b_); //<-- returns c_1 = non-null(actual pointer value)
    c *c_2 = dynamic_cast<c*>(a_); //<-- returns c_2 = NULL
}

I believe the author has all the classes set up properly for dynamic_cast<>(). Class c 'is a' Class a so that seems satisfied, and Class c 'is a' Class b so that seems satisfied.

I'm wondering if the problem lies in the fact that a_ is actually a derived Class b, which could theoretically be in fact a derived pointer to a hypothetical Class d. I'm rusty on my c++ and I could use some help here as to the root cause and a proper solution.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Gio
  • 4,099
  • 3
  • 30
  • 32
  • Not the problem but you can get rid of `virtual` in all the derived classes. virtualness in inherited and doesn't need to be explicitly stated in derived classes. – NathanOliver Jan 11 '19 at 22:40
  • Though I'm not sure why c_2 is NULL... – Gio Jan 11 '19 at 22:42
  • 5
    What is the behavior you are expecting? `a_` points to a `b`, which is _not_ a `c`, so returning `nullptr` is correct. – Travis Gockel Jan 11 '19 at 22:42
  • Are you execting dynamic_cast to create a new `c` object? It doesn't work like that. – john Jan 11 '19 at 22:46
  • As I added below, I was having a moment of 'non clarity'...sigh. I got strung up on the 'is a' aspect. But that's what SO is for right? Thanks for all of the help. – Gio Jan 11 '19 at 23:00
  • If that were to return a pointer, what instance of `class c` would it point to? – David Schwartz Jan 11 '19 at 23:20
  • So I am a bit confused here. I(we) get down voted because we got hung up on a concept, a group of 5 after a hard week on a Friday afternoon. So we turned to SO for some clarity, knowing that we were probably missing something obvious. Sort of not being able to see the forest through the trees. I thought that, at least in part was what SO was for. Being able to turn to a group of like minded individuals, who in all likely hood have struggled over something that after some outside intervention was suddenly clear. Am I missing something or has SO changed so much over the years ? – Gio Jan 12 '19 at 01:26

1 Answers1

6

a_ points to a b. When you attempt dynamic_cast<c*>(a_); to try to get a c out of it there is no c object, only a b so the cast fails and you get a null pointer. b_ works becuase b_ actually points to a c.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I see: there is no guarantee that a_ points to a c object. Couldn't get past that, though I do wonder if the dynamic_cast method couldn't have followed the RTTI chain. – Gio Jan 11 '19 at 22:45
  • @Gio its not about guarantees, what matters is that in fact at the time the dynamic_cast is performed `a_` is not pointing at a `c` object. – john Jan 11 '19 at 22:48
  • @Gio It is guaranteed not to point to a `c` object in the code you've shown. – juanchopanza Jan 11 '19 at 22:48
  • After a few more minutes I get it now: as pointed out a_ points to a b object and nothing more. Sorry for the slow uptake - tried to edit my last comment but it timed out. – Gio Jan 11 '19 at 22:52
  • 2
    @Gio: "Followed the RTTI chain" to where? Your `a_` is not `c`. There's no "RTTI chain" that leads to a `c` object from `a_`. "Following the RTTI chain" is actually exactly what `dynamic_cast` attempted to do. And that chain did not lead to `c`. That why you got null pointer as result. – AnT stands with Russia Jan 11 '19 at 22:52