1

As we knew, In order to avoid memory leak, we had better to use SmartPtr to managing the object instead of common pointer.

In most cases, it works very well.

Now I have encountered a problem, I tried my best to describe it more simply.

I have a base class:

class Base;

I have another two classes inherited from base class:

class Derive1 : public Base;

class Derive2 : public Base;

If I use raw pointer, I can implement polymorphic easily;

Base *pd1 = new Derive1();

Base *pd2 = new Derive2();

But If I want to use smartPtr to implement the same thing how should I to do? For example:

SmartPtr<Base> pd1 = SmartPtr<Derive1>(new Derive1);

Is there smartPtr to support the transformation, or shall I need to implement a template of smartPtr, but If I implement the template by myself, how to avoid the code bloating,who has good advice?

If there is a template smartPtr supporting this operation, how do it accomplish this function? as we know a base pointer can point to a derived object, but it is bad in turn!!

Felix Glas
  • 15,065
  • 7
  • 53
  • 82
minicaptain
  • 1,196
  • 9
  • 16
  • 1
    You didn't really implement your own `SmartPtr`, did you? – Brian Cain Jul 24 '13 at 13:45
  • My advice: go and implement it, then use `std::shared_ptr` or some other `std::*_ptr`. – user1095108 Jul 24 '13 at 13:50
  • @Brian Cain yes really!I just do not to how implement a universal template to support different base class and derived class to transform,because a base class ptr can point to a derived object,but a derived class ptr can not point to a base object,I did not know how to control it! – minicaptain Jul 24 '13 at 13:52
  • 2
    @minicaptain, I think Brian's point was that you shouldn't implement your own, when there are `std::unique_ptr` and `std::shared_ptr` available. – avakar Jul 24 '13 at 14:03
  • Yes you are right,I want to know how the unique_ptr and shared_ptr to support this function? – minicaptain Jul 24 '13 at 14:05

4 Answers4

4

Destroying the object will work correctly, so long as you have a virtual destructor in Base:

class Base {
  public:
    virtual ~Base();
    ...
};
cdmh
  • 3,294
  • 2
  • 26
  • 41
  • yes,I know this,but I want to know how the smartptr to support polymorphic! – minicaptain Jul 24 '13 at 14:04
  • ok, the smart pointer will `delete` the object of type `Base` when the reference count reaches 0. `delete` of a type `Base` will invoke the destructor chain, which will destroy the derived type if the `Base` dtor is virtual. – cdmh Jul 24 '13 at 14:06
  • I think you do not understand my question, I want to know how does a template to distinguish a base and derived object,you know a base pointer can point to a derived object, but it is bad in turn!! – minicaptain Jul 24 '13 at 14:09
  • Sorry, I'm not sure what the question is. The template itself doesn't know about the derived object. It contains and manages a pointer to the base class. The C++ language defines how polymorphism works for an object hierarchy. The template isn't doing anything with the hierarchy because it doesn't know about it. Does that help? – cdmh Jul 24 '13 at 14:15
1

If you're talking about std::shared_ptr<T> or unique_ptr<T>, then yes, it will handle that case because internally it stores data of the type T*, in this case Base*. So you are fine using it that way. They wouldn't be of much use otherwise.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • thanks Seth!! I also want to know how does share_ptr or unique_ptr to support this tranformation? you know a base class ptr can point to a derived object,but a derived class ptr can not point to a base object,how to do it in a template! – minicaptain Jul 24 '13 at 13:55
1

You don't need to implement your own smart pointer template, use std::unique_ptr or std::shared_ptr.

For example, this will work just the way you want, exploiting polymorphic behaviour.

std::unique_ptr<Base> sptr1{new Derive1()};
std::unique_ptr<Base> sptr2{new Derive2()};

That is, you can use sptr1 & sptr2 in the same way as:

Base* pd1 = new Derive1();
Base* pd2 = new Derive2();

When sptr1 & sptr2 goes out of scope then the destructor Base::~Base() will be called and the internal pointer to the Base-object will be deleted. Make ~Base() virtual to also call ~Derive1() and ~Derive2() respectively, upon destruction (same as you would do without the smart pointer).

Live example: http://ideone.com/zVebLV

To make sptr1 point to another derived object do like this:

sptr1 = sptr2; // This will destruct previous object pointed to by sptr1.
               // Will also set sptr2 = nullptr.

More info about smart pointers: C++11 Smart Pointer Policies

Community
  • 1
  • 1
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
1

I think you're asking 'how should this line code work?'?

SmartPtr<Base> pd1 = SmartPtr<Derive1>(new Derive1);

The best advice I have is to look at boost or similar source for shared_ptr. Basically it uses a templated constructor, allowing you to construct one shared pointer from another. Obviously the underlying pointer types have to be compatible...

template<class Y> shared_ptr( shared_ptr<Y> const & r )
: px( r.px ), pn( r.pn ) 
{
}

Of course, you could avoid this, by just writing this instead in the first place:-

SmartPtr<Base> pd1(new Derive1);
Roddy
  • 66,617
  • 42
  • 165
  • 277
  • +1, beat me to it, I also think this is what the OP is actually asking, not assigning a `Derived` raw pointer to a `Base` smart pointer like the other answers seem to explain. – KillianDS Jul 24 '13 at 14:41