В новом фрагменте кода у меня есть несколько разных классов, которые ссылаются друг на друга.Примерно так (это не моя настоящая ситуация, а пример чего-то похожего):
class BookManager
{
...
};
class Book
{
public:
void setBookManager(BookManager *bookManager) {m_bookManager = bookManager;}
private:
BookManager *m_bookManager;
};
Каждая книга относится к менеджеру книг, но проблема в том, что многие книги будут иметь свой собственный BookManager, нонекоторые книги могут иметь общий BookManager.
На самом деле вызывающая сторона не указывает, что Книга должна делать со своим BookManager, но в 90% случаев BookManager может быть уничтожен вместе с Книгой.Примерно в 10% случаев один и тот же BookManager используется повторно для нескольких книг, и BookManager нельзя удалять вместе с Книгой.
Удаление BookManager вместе с Книгой удобно в этих 90% случаев.так как вызывающая сторона Book :: setBookManager больше не должна помнить BookManager.Он просто умирает вместе с самой Книгой.
Я вижу два альтернативных решения этой проблемы.
Во-первых, это широкое использование общих указателей.Если после этого вызывающий абонент больше не интересуется BookManager, он не сохраняет общий указатель на него.Если он по-прежнему заинтересован в этом или хочет, чтобы BookManager использовался совместно несколькими книгами, он сохраняет общий указатель и передает его этим нескольким книгам.
Второй альтернативой является явное указание Книге, чточтобы сделать с владельцем книги, как это:
class Book
{
public:
void setBookManager(BookManager *bookManager, book takeOwnership=true)
{
m_bookManager = bookManager;
m_hasOwnership = takeOwnership;
}
~Book()
{
if (m_hasOwnership && m_bookManager) delete m_bookManager;
}
private:
BookManager *m_bookManager;
bool m_hasOwnership;
};
Второе решение кажется гораздо проще и позволяет нам использовать обычный синтаксис указателя (BookManager *
в отличие от std::shared_ptr<BookManager>
), но кажетсяменее «чистый», чем подход с общим указателем.
Другой альтернативой может быть использование typedef в BookManager, например:
class BookManager
{
public:
typedef std::shared_ptr<BookManager> Ptr;
...
};
, что позволяет нам написать это:
BookManager::Ptr bookManager;
Что больше похоже на обычный синтаксис указателя, чем на оригинальный синтаксис общего указателя.
Кто-нибудь имеет опыт работы с любым из этих подходов?Любые другие предложения?