std::unique_ptr with derived class

38,639

If they are polymorphic types and you only need a pointer to the derived type use dynamic_cast:

Derived *derivedPointer = dynamic_cast<Derived*>(basePointer.get());

If they are not polymorphic types only need a pointer to the derived type use static_cast and hope for the best:

Derived *derivedPointer = static_cast<Derived*>(basePointer.get());

If you need to convert a unique_ptr containing a polymorphic type:

Derived *tmp = dynamic_cast<Derived*>(basePointer.get());
std::unique_ptr<Derived> derivedPointer;
if(tmp != nullptr)
{
    basePointer.release();
    derivedPointer.reset(tmp);
}

If you need to convert unique_ptr containing a non-polymorphic type:

std::unique_ptr<Derived>
    derivedPointer(static_cast<Derived*>(basePointer.release()));
Share:
38,639

Related videos on Youtube

Lukas Schmit
Author by

Lukas Schmit

Updated on July 04, 2020

Comments

  • Lukas Schmit
    Lukas Schmit almost 4 years

    I have a question about the c++11 pointers. Specifically, how do you turn a unique pointer for the base class into the derived class?

    class Base
    {
    public:
       int foo;
    }
    
    class Derived : public Base
    {
    public:
       int bar;
    }
    
    ...
    
    std::unique_ptr<Base> basePointer(new Derived);
    // now, how do I access the bar member?
    

    it should be possible, but I can't figure out how. Every time I try using the

    basePointer.get()
    

    I end up with the executable crashing.

    Thanks in advance, any advice would be appreciated.

    • jogojapan
      jogojapan almost 11 years
      Could you show a complete (but minimal) example of the code that causes your process to crash? basePointer.get() alone certainly isn't a problem.
    • Lukas Schmit
      Lukas Schmit almost 11 years
      @jogojapan I fixed my problem. I was doing some really weird casting with at least 5 sets of parenthesis. I'm pretty sure it was just something stupid, but I already changed it and don't remember what I did. Captain Obvlious' answer worked for me though. Thanks for all your help!
  • Marc
    Marc over 7 years
    Are you sure there's no memory leak when you do basePointer.release()?
  • Captain Obvlious
    Captain Obvlious over 7 years
    @Marc Yes, I'm sure.
  • meneldal
    meneldal over 6 years
    @Marc The reason it is safe is because both release() and reset() are noexcept, so unless you are doing something very bad outside this function, the raw pointer will always end up in the derived pointer and will be correctly destroyed.
  • Masadow
    Masadow over 5 years
    It might be obvious for some but please note that you are stealing the resource from the basePointer which is not always what you want in your unique_ptr conversion
  • Daniel McLaury
    Daniel McLaury over 4 years
    @Masadow: If it's not what you want, then you don't want a unique pointer.
  • Charles Gueunet
    Charles Gueunet over 3 years
    can't we just use a std::move instead of cast + release ?
  • Johan Boulé
    Johan Boulé over 3 years
    Problem with the answer. Yes, static_cast does also support polymorphic types. You should only use dynamic_cast when you're unsure whether the cast will work or fail (and in this case, test whether it returned null as you did).