2010-12-07 6 views
0

Prenons l'exemple suivant:Pouvez-vous mélanger des pointeurs partagés avec des membres de données sans pointeur?

class BookManager 
    { 
    ... 
    }; 

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

Depuis l'appelant est généralement pas intéressé à garder un BookManager pour un livre si le livre est supprimé, et depuis plusieurs livres peuvent partager un BookManager, je fais le pointeur vers BookManager, un pointeur partagé, comme ceci:

typedef std::shared_ptr<BookManager> BookManagerPtr; 

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

le problème est qu'un module dans mon application a sa propre BookManager qu'il veut donner à chacun de ses livres, comme ceci:

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

Bien sûr, cela ne fonctionne pas car le dernier livre supprimé supprime également l'instance de BookManager, qu'il ne doit pas supprimer car il s'agit d'un membre normal de MyModule.

Cela signifie que MyModule doit également utiliser un pointeur partagé à BookManager, comme ceci:

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

Est-ce la seule façon de résoudre ce problème? Ou existe-t-il un moyen d'avoir toujours des membres de données normaux et d'utiliser des pointeurs partagés (par exemple, en initialisant son compte de référence à 1)?

+0

Veillez à ne pas utiliser de pointeur partagé sans nom comme dans la première version de MyModule :: createBook(). Voir http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm#BestPractices –

Répondre

2

de créer une copie BookManagerPtr(new BookMarkManager(m_bookManager)), de faire m_bookManager un BookManagerPtr aussi ou faire un livre un modèle lui permettant ainsi d'utiliser BookManager * et shared_ptr. shared_ptr concerne la propriété partagée, dans votre exemple MyModule possède l'exemple et le livre n'est pas compatible avec shared_ptr

1

Qu'en est-il de l'utilisation de Deleter personnalisé qui ne fait rien?

1

Je sais que vous avez accepté une réponse, mais une autre approche (si vous avez boost) pourrait être d'utiliser des références. Par défaut vous ne pouvez pas avoir un membre de référence dans la classe Book, cependant si vous l'intégrez dans un boost::optional<BookManager&> optionnel alors vous pouvez avoir une référence, ensuite, dans la méthode setBookManager, passer la référence (ou la référence const) et assigner ceci à l'optionnel. Pour l'utiliser, deref comme vous le feriez d'un pointeur intelligent ...

0

Le moyen sûr de modèle non-propriété est une weak_ptr ainsi la durée de vie est toujours contrôlée par MyModule tout en ayant Book référence un BookManager et savoir si le BookManager Les références sont toujours valables.

Questions connexes