C++ Cast base class unique_ptr to derived class unique_ptr [duplicate]

11 hours ago 1
ARTICLE AD BOX

How do I cast my unique_ptr to the base class to allow me to call the method in the derived class?

You don't cast the unique_ptr itself, you cast the pointer that the unique_ptr is holding.

Also, your code would invoke Undefined Behavior for trying to call a method via a pointer that doesn't point at a valid object. You need to create the Derived object before you can call anything on it, eg:

std::unique_ptr<Base> basePtr = std::make_unique<Derived>();

Now, as stated in comments, the issue has nothing to do with std::unique_ptr at all, so let's just eliminate it and simplify the code a little:

#include <iostream> class Base { public: Base() {}; }; class Derived: public Base { public: Derived() {}; void Mathod() { std::cout << "Derived method" << std::endl; } }; int main() { Derived derivedObj; Base *basePtr = &derivedObj; basePtr->Mathod(); // How to cast basePtr to call Method() ? return 0; }

To answer your question - in order to call Derived::Mathod() via a Base* pointer, you have two choices:

add Mathod to Base as a virtual method that Derived can override, eg:

class Base { public: Base() {}; virtual void Mathod() = 0; }; class Derived: public Base { public: Derived() {}; void Mathod() override { std::cout << "Derived method" << std::endl; } }; int main() { Derived derivedObj; Base *basePtr = &derivedObj; basePtr->Mathod(); // Works return 0; }

cast the Base* pointer to a Derived* pointer. There are 3 casts you could choose from:

static_cast

Use static_cast only when you KNOW 100% FOR SURE that the Base* pointer is pointing at a Derived object. This is the most direct, as it is resolved at compile-time. The compile will fail if the two pointer types are not compatible with each other.

static_cast<Derived*>(basePtr)->Mathod(); dynamic_cast

Use dynamic_cast when you DON'T KNOW at compile-time whether the Base* pointer is pointing at a Derived object, ie if there are other classes present that are derived from Base but are unrelated to Derived. This cast is resolved at runtime using RTTI, so you have to check the result to make sure the cast is successful before using the casted pointer, eg:

class Base { public: Base() {}; }; class Derived: public Base { public: Derived() {}; void Mathod() { std::cout << "Derived method" << std::endl; } }; class Derived2: public Base { public: Derived2() {}; void Mathod() { std::cout << "Derived2 method" << std::endl; } }; int main() { Derived derivedObj; Derived2 derived2Obj; Base *basePtr = &derivedObj; Derived *d = dynamic_cast<Derived*>(basePtr); // SUCCEEDS if (d) d->Mathod(); // CALLED basePtr = &derived2Obj; d = dynamic_cast<Derived*>(basePtr); // RETURNS nullptr if (d) d->Mathod(); // NOT CALLED return 0; } reinterpret_cast

While technically legal, don't use reinterpret_cast at all in this situation. It makes no guarantees about compatibility/safely between the two pointer types. It's literally no different than casting the Base* pointer to void* and then casting that to Derived*.

reinterpret_cast<Derived*>(basePtr)->Mathod(); // same as: // static_cast<Derived*>(static_cast<void*>(basePtr))->Mathod();

Lastly, you can still apply these techniques even when using std::unique_ptr. You just need to access its raw pointer, eg:

std::unique_ptr<Base> basePtr = std::make_unique<Derived>(); basePtr->Mathod(); // Works if Mathod() is virtual in Base... static_cast<Derived*>(basePtr.get())->Mathod(); // Works if basePtr is pointing at a Derived object... Derived *d = dynamic_cast<Derived*>(basePtr.get()); if (d) d->Mathod(); // Works if basePtr is pointing at a Derived object...
Read Entire Article