51

I have two classes A and B, B inherits from A.

If I have a shared_ptr<A> object which I know is really a B subtype, how can I perform a dynamic cast to access the API of B (bearing in mind my object is shared_ptr, not just A?

intrigued_66
  • 16,082
  • 51
  • 118
  • 189

3 Answers3

89

If you just want to call a function from B you can use one of these:

std::shared_ptr<A> ap = ...;
dynamic_cast<B&>(*ap).b_function();
if (B* bp = dynamic_cast<B*>(ap.get()) {
    ...
}

In case you actually want to get a std::shared_ptr<B> from the std::shared_ptr<A>, you can use use

std::shared_ptr<B> bp = std::dynamic_pointer_cast<B>(ap);
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 1
    `dynamic_cast(*ap).b_function();` if you are doing this, what is the point of the dynamic_cast. You don't check the result anyway, you would just use `static_cast` here. I think only the `if(B* bp = ...` and the `dynamic_pointer_cast` are correct here. – Fantastic Mr Fox Dec 27 '18 at 15:07
  • @FantasticMrFox: a `static_cast(a)` can only be used if `a` was obtained from an implicit conversion from a `B*`. Of the conversion was from a further derived type or from a sibling class in a scenario involving multiple inheritance the `dynamic_cast` has defined behavior while the `static_cast` has not. – Dietmar Kühl Dec 27 '18 at 23:35
  • `dynamic_pointer_cast` was exactly what I was looking for (as opposed to `dynamic_cast`) – RoG Apr 05 '22 at 14:01
  • @FantasticMrFox You don't need to check the result of the dynamic_cast on reference types... how/what would you check? The specified behavior of dynamic_cast is to throw a std::bad_cast exception when casting references would fail. – Chris Uzdavinis Jun 16 '23 at 22:46
20

use dynamic_pointer_cast

example copied from above link

// static_pointer_cast example
#include <iostream>
#include <memory>

struct A {
  static const char* static_type;
  const char* dynamic_type;
  A() { dynamic_type = static_type; }
};
struct B: A {
  static const char* static_type;
  B() { dynamic_type = static_type; }
};

const char* A::static_type = "class A";
const char* B::static_type = "class B";

int main () {
  std::shared_ptr<A> foo;
  std::shared_ptr<B> bar;

  bar = std::make_shared<B>();

  foo = std::dynamic_pointer_cast<A>(bar);

  std::cout << "foo's static  type: " << foo->static_type << '\n';
  std::cout << "foo's dynamic type: " << foo->dynamic_type << '\n';
  std::cout << "bar's static  type: " << bar->static_type << '\n';
  std::cout << "bar's dynamic type: " << bar->dynamic_type << '\n';

  return 0;
}

output

foo's static  type: class A
foo's dynamic type: class B
bar's static  type: class B
bar's dynamic type: class B
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
2

Probably the nicest way would be to use the standard functions for casting a shared_ptr

RamblingMad
  • 5,332
  • 2
  • 24
  • 48