Click here to Skip to main content
Click here to Skip to main content

Tagged as

shared_ptr and the class factory

, 9 Aug 2012
Rate this:
Please Sign up or sign in to vote.
shared_ptr and the class factory

Introduction

We have a device manager that keeps track of currently attached devices. They happen to be USB devices but that is irrelevant. The issue we face is that devices can be attached or removed at any time. The class factory will scan the list of currently attached devices and if found, returns a shared_ptr to that device. If the device is removed the device manager will remove the object from the list, which will delete the object. This is bad news for any routines currently using a pointer to that object. The object needs to be kept alive until all routines using that device let go. This is an ideal application of the shared_ptr.

My problem is the usual hierarchy doesn’t work with shared_ptr.

class Base {};
class DeviceOne : public Base {};
class DeviceTwo : public Base{};
shared_ptr<Base> classfactory( string const &dev ) {};

// compile error
shared_ptr<DeviceOne> d1 = classfactory( "deviceone");

// compile error	
shared_ptr<DeviceTwo> d2 = classfactory("devicetwo");

// can’t use d3 as a DeviceOne object		
shared_ptr<Base> d3 = classfactory("deviceone");

classfactory has to return a shared_ptr<Base>. The way I solved the problem was to define a class that keeps the device object alive by protecting the object instance, while allowing convenient access to what it points to. It does add another pointer to overhead, but I thought it was worth it. The extra pointer can be removed. Just modify the operator->() to return the dynamic_cast. Since there is a runtime penalty for dynamic_cast, I chose to only pay for that once, at the cost of the extra pointer memory.

template<typename T>
class PDerrived 
{
public:
	PDerrived( shared_ptr<Base> p_ )
		: b(p_)					// keep the device alive
		, pd( dynamic_cast<T *>(p_.get()) )	// cached for convenience
	{}
    
    // convenient access to object
	T *operator->() const { return pd; }	
	
	// object created and correct type
	operator bool () const { return pd != nullptr; }
	
	// allows assignment to other shared_ptrs
	operator shared_ptr<Base> () const { return b; }	
private:
shared_ptr<Base>	b;
	T 			*pd;
};

//Now one can write
PDerrived <deviceOne> d1 = classfactory( "deviceone");
PDerrived <deviceTwo> d2 = classfactory("devicetwo");
PDerrived <Base> p = d1;

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

mzdude

United States United States
No Biography provided

Comments and Discussions

 
Questionnice tip PinmemberVolynsky Alex9-Aug-12 14:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 9 Aug 2012
Article Copyright 2012 by mzdude
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid