32

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.

banarun
  • 2,305
  • 2
  • 23
  • 40
Lukas Schmit
  • 1,118
  • 2
  • 9
  • 14
  • 3
    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. – jogojapan Jul 02 '13 at 05:26
  • @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! – Lukas Schmit Jul 02 '13 at 05:32

1 Answers1

57

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()));
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • Are you sure there's no memory leak when you do basePointer.release()? – Marc Dec 08 '16 at 16:37
  • @Marc Yes, I'm sure. – Captain Obvlious Dec 08 '16 at 16:48
  • 3
    @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. – meneldal Jan 09 '18 at 06:45
  • 1
    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 – Masadow Jan 09 '19 at 13:27
  • 3
    @Masadow: If it's not what you want, then you don't want a *unique* pointer. – Daniel McLaury Jan 23 '20 at 18:33
  • can't we just use a std::move instead of cast + release ? – Charles Gueunet Jan 29 '21 at 09:42
  • 2
    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). – Johan Boulé Feb 03 '21 at 11:38