2010-12-07 7 views
0

Nehmen Sie das folgende Beispiel:Können Sie gemeinsam genutzte Zeiger mit Nicht-Zeiger-Datenelementen mischen?

class BookManager 
    { 
    ... 
    }; 

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

Da der Anrufer der Regel nicht daran interessiert ist, einen Bookmanager für ein Buch zu halten, wenn das Buch gelöscht wird, und da mehr Bücher einen Bookmanager teilen können, mache ich den Zeiger auf Bookmanager, ein gemeinsamer Zeiger, wie folgt aus:

typedef std::shared_ptr<BookManager> BookManagerPtr; 

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

Problem ist, dass ein Modul in meiner Anwendung einen eigenen Book hat, dass es zu jedem seiner Bücher geben will, wie folgt aus:

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

Natürlich funktioniert das nicht, weil das letzte gelöschte Buch auch die BookManager-Instanz löscht, die es nicht löschen sollte, weil es ein normales Datenelement von MyModule ist.

Dies bedeutet, dass MyModule auch einen gemeinsamen Zeiger auf Bookmanager, wie diese verwendet werden soll:

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

Ist dies der einzige Weg, um dieses Problem lösen? Oder gibt es eine Möglichkeit, noch normale Datenelemente zu haben und gemeinsame Zeiger zu verwenden (z. B. durch Initialisieren der Referenzzählung auf 1)?

+0

Achten Sie darauf, keinen unbenannten gemeinsamen Zeiger wie in der ersten Version von MyModule :: createBook() zu verwenden. Siehe http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm#BestPractices –

Antwort

2

erstellen Sie eine Kopie BookManagerPtr(new BookMarkManager(m_bookManager)), machen Sie m_bookManager auch zu BookManagerPtr oder machen Sie eine Vorlage, so dass Sie BookManager * und shared_ptr verwenden können. shared_ptr ist über die gemeinsame Eigentümerschaft, in Ihrem Beispiel MyModule besitzt das Beispiel und Buch nicht, so dass es nicht mit shared_ptr kompatibel ist

1

Was ist mit der Verwendung benutzerdefinierte Deleter, die nichts tut?

1

Ich weiß, dass Sie eine Antwort akzeptiert haben, aber ein anderer Ansatz (wenn Sie Boost haben) könnte die Verwendung von Referenzen sein. Standardmäßig können Sie kein Referenzelement in der Klasse Book haben. Wenn Sie es jedoch in ein optionales Element, z. B. boost::optional<BookManager&>, einbinden, können Sie als nächstes in der Methode eine Referenz angeben (oder const-Referenz) und zuweisen dies zu den optionalen. Zur Verwendung deref wie Sie einen Smart-Pointer würden ...

0

Der sichere Weg nicht-Eigentum mit einem auf diese Weise weak_ptr ist modellieren die Lebensdauer noch von MyModule gesteuert wird, während immer noch Book ein BookManager Referenz mit und wissen, ob die BookManager es Referenzen sind noch gültig.

Verwandte Themen