Можете ли вы смешивать общие указатели с не указателями членов данных? - PullRequest
0 голосов
/ 07 декабря 2010

Возьмите следующий пример:

class BookManager
   {
   ...
   };

class Book
   {
   public:
      void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
   private:
      BookManager *m_bookManager;
   };

Поскольку вызывающий объект обычно не заинтересован в сохранении BookManager для Книги, если Книга удалена, и так как BookManager могут использовать несколько Книг, я делаю указатель на BookManager, общий указатель, например:

typedef std::shared_ptr<BookManager> BookManagerPtr;

class Book
   {
   public:
      void setBookManager(BookManagerPtr bookManager) {m_bookManager = bookManager;}
   private:
      BookManagerPtr m_bookManager;
   };

Проблема в том, что модуль в моем приложении имеет собственный BookManager, который он хочет передать каждой своей книге, например:

class MyModule
   {
   public:
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(BookManagerPtr(&m_bookManager));
         }
   private:
      BookManager m_bookManager;
   };

Конечно, это не работает, потому что последняя удаленная книга также удалит экземпляр BookManager, который он не должен удалять, поскольку он является обычным элементом данных MyModule.

Это означает, что MyModule должен также использовать общий указатель на BookManager, например:

class MyModule
   {
   public:
      MyModule()
      : m_bookManager(new BookManager())
         {
         }
      Book *createBook()
         {
         Book *newBook = new Book();
         newBook->setBookManager(m_bookManager);
         }
   private:
      BookManagerPtr m_bookManager;
   };

Это единственный способ решить это? Или есть способ сохранить обычные элементы данных и использовать для них общие указатели (например, путем инициализации счетчика ссылок равным 1)?

Ответы [ 4 ]

2 голосов
/ 07 декабря 2010

создайте копию BookManagerPtr(new BookMarkManager(m_bookManager)), сделайте m_bookManager тоже BookManagerPtr или сделайте книгу шаблоном, что позволит использовать BookManager * и shared_ptrshared_ptr касается совместного владения, в вашем примере MyModule владеет примером, а книга - нет, поэтому он не совместим с shared_ptr

1 голос
/ 07 декабря 2010

Я знаю, что вы приняли ответ, но другим подходом (если у вас есть повышение) может быть использование ссылок.По умолчанию у вас не может быть ссылочного члена в классе Book, однако, если вы заключите его в необязательный, например, boost::optional<BookManager&>, тогда вы можете иметь ссылку, затем, в методе setBookManager, передать ссылку (или const reference) и присвойте его необязательному.Чтобы использовать, дереф как умный указатель ...

1 голос
/ 07 декабря 2010

Как насчет использования пользовательского средства удаления, которое ничего не делает?

0 голосов
/ 07 декабря 2010

Безопасный способ смоделировать отсутствие владения - это weak_ptr, таким образом, время жизни по-прежнему контролируется MyModule, при этом Book ссылается на BookManager и знает, что BookManager, на которое оно ссылается, все ещедействительный.

...