1

I have a function that takes a reference to a base object (used as an output parameter). That function must create a derived object and pass it back to the caller through that reference.

The caller calls that function by dereferencing a pointer to base (in this case a smart ptr), and passing it as the argument to the function.

The problem is that even though the function changes the underlying object, the caller still can't cast the pointer to the derived object:

#include <iostream>
#include <memory>
using namespace std;

struct Base {
  virtual void id() { cout << "Base" << endl; }
};

struct Derived: Base {
  void id() override { cout << "Derived" << endl; }
};

void get_derived(Base &b) {
  b = Derived();
  b.id();         //Still prints "Base"
}

int main() {

  auto b = make_shared<Base>();
  b->id(); //prints "Base"
  get_derived(*b);
  b->id(); //prints "Base" still

  auto f = dynamic_pointer_cast<Derived>(b);
  if(!f) cout << "cast failed" << endl; //this branch taken
  else cout << "cast succeeded" << endl;
}

Why is it that after b = Derived(), the pointer to id() in the virtual table of b still points to Base's id() function instead of Derived's vtable? And how do I change get_derived() to make the b reference refer to a Derived object? Note: I can't change the signature of get_derived()

plg
  • 13
  • 3
  • `b = Derived();` is assigning the value of a default constructed `Derived` to `b`. It does not change what `b` refers to or that object's type. An object's type cannot change at runtime. – François Andrieux Jan 17 '20 at 16:07
  • @FrançoisAndrieux So basically there is no way that `get_derived` can pass a full `Derived` object back to the caller, so I have to make a new function that takes a `shared_ptr` instead correct? Something like: ```lang-cpp void get_derived2(shared_ptr &b){ b = make_shared(); b->id(); } ``` – plg Jan 17 '20 at 16:16
  • You can change `get_derived` to take a `std::shared_ptr &` and assign to it to the result of a `std::make_shared()`. What that does is create an actual `Derived` and changes what `b` refers to. Edit : Missed your edit. What you wrote seems to be right. – François Andrieux Jan 17 '20 at 16:19
  • @FrançoisAndrieux: Ok thank you! – plg Jan 17 '20 at 16:21

0 Answers0