Take the following example:
class BookManager
{
...
};
class Book
{
public:
void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
private:
BookManager *m_bookManager;
};
Since the caller is typically not interested in keeping a BookManager for a Book if the Book is deleted, and since multiple Books can share a BookManager, I make the pointer to BookManager, a shared pointer, like this:
typedef std::shared_ptr<BookManager> BookManagerPtr;
class Book
{
public:
void setBookManager(BookManagerPtr bookManager) {m_bookManager = bookManager;}
private:
BookManagerPtr m_bookManager;
};
Problem is that a module in my application has its own BookManager that it wants to give to each of its books, like this:
class MyModule
{
public:
Book *createBook()
{
Book *newBook = new Book();
newBook->setBookManager(BookManagerPtr(&m_bookManager));
}
private:
BookManager m_bookManager;
};
Of course this doesn't work because the last deleted book will also delete the BookManager instance, which it shouldn't delete because it's a normal data member of MyModule.
This means that MyModule should also use a shared pointer to BookManager, like this:
class MyModule
{
开发者_开发问答public:
MyModule()
: m_bookManager(new BookManager())
{
}
Book *createBook()
{
Book *newBook = new Book();
newBook->setBookManager(m_bookManager);
}
private:
BookManagerPtr m_bookManager;
};
Is this the only way to solve this? Or is there a way to still have normal data members and use shared pointers to it (e.g. by initializing its reference count to 1)?
create a copy BookManagerPtr(new BookMarkManager(m_bookManager))
, make m_bookManager a BookManagerPtr too or make book a template thus allowing it to use BookManager* and shared_ptr.
shared_ptr is about shared ownership, in your example MyModule owns the example and book don't, so it's not compatible with shared_ptr
What about using custom deleter which does nothing?
I know you've accepted an answer, but another approach (if you have boost) could be to use references. By default you can't have a reference member in the Book
class, however if you wrap it in an optional i.e. boost::optional<BookManager&>
then you can have a reference, next, in the setBookManager
method, pass in the reference (or const reference) and assign this to the optional. To use, deref as you would a smart pointer...
The safe way to model non-ownership is with a weak_ptr
this way the lifetime is still controlled by MyModule
while still having Book
reference a BookManager
and know if the BookManager
it references is still valid.
精彩评论