Spezielle Frage zu den Möglichkeiten von C++
-
-
Du kannst ein nicht-kopierbares Objekt zurückgeben, das den Zeiger kapselt.
-
wrapper schrieb:
Du kannst ein nicht-kopierbares Objekt zurückgeben, das den Zeiger kapselt.
Was aber die vollständige Schnittstelle des Objektes Anbieten muss, da man sonst ebenso an den Zeiger gelangt (Effektiv ein Proxy Entwurfsmuster)...
-
Ich denke auch, um einen Proxy kommt man nicht drumherum.
-
asc schrieb:
Was aber die vollständige Schnittstelle des Objektes Anbieten muss, da man sonst ebenso an den Zeiger gelangt (Effektiv ein Proxy Entwurfsmuster)...
Adressoperator verbieten.

-
Also das mit dem Stellvertreter finde ich schonmal gut.
Mal sehen, ob sich der Aufwand lohnt. Da muss ich nochmal drüber nachdenken.Wie kann ich den Adressoperator verbieten???
Grüße und Vielen Dank an alle die antworten!
Timo
-
horscht2999 schrieb:
Wie kann ich den Adressoperator verbieten???
Das müsstest du nur machen, wenn man über den Stellvertreter (Proxy) direkt auf das Objekt zugreifen kann.
Also entweder man macht einen vollständigen Adapter wie von wrapper vorgeschlagen:
class Bar { public: BarMethod1(); BarMethod2(); }; class BarWrapper { private: Bar* MyPtr; public: BarMethod1(); // Interface von Bar wird hier übernommen BarMethod2(); };Oder, wenn man das Objekt direkt zurückgeben will, muss man dafür sorgen, dass man dessen Adresse nicht über den Adressoperator bekommt.
class Bar { private: Bar* operator&(); // Adressoperator privat, um Zugriff zu verhindern public: BarMethod1(); BarMethod2(); }; class BarProxy { private: Bar* MyPtr; public: Bar& GetBar(); // Zugriff auf das Objekt dahinter. Man erfährt nie dessen Adresse. };Aber Adressoperatoren zu verbieten ist nicht unbedingt schön. Zumal es Hacks wie
boost::adressofgibt...
-
Sag doch ma bitte, wieso du es genau brauchst
um was für objekte geht es?
wieso ist die prüfung erforderlich?
was würde passieren, wenn er das objekt doch speichern würde?
ändert sich die adresse des objektes denn?
wie würde ein aufruf denn aussehen?
also:Foo::GetBar()->doA(); Foo::GetBar()->doB();oder anders?
etc.bb
-
Also ich habe das Problem jetzt folgendermaßen gelöst:
Habe ich vielleicht was übersehen. Bei meinen Tests hat der Kompiler, bei jeder Zuweisung geschimpft.namespace bip = boost::interprocess; class queries_list { public: static queries_list& get_instance(const bip::sharable_lock<bip::interprocess_upgradable_mutex>& list_lock) throw (std::invalid_argument); static queries_list& get_instance(const bip::upgradable_lock<bip::interprocess_upgradable_mutex>& list_lock) throw (std::invalid_argument); static queries_list& get_instance(const bip::scoped_lock<bip::interprocess_upgradable_mutex>& list_lock) throw (std::invalid_argument); static bool destroy_instance(const bip::scoped_lock<bip::interprocess_upgradable_mutex>& list_lock, bool wait = false) throw (std::invalid_argument); static bip::interprocess_upgradable_mutex list_mutex; ... weitere nicht statische Methoden ... private: queries_list(); virtual ~queries_list(); queries_list* operator&(); queries_list(const queries_list& other); };Um die vorherige Frage zu beantworten. Das Ganze soll ein Singleton Entwurfsmuster werden, bei dem die Instanz nur zurückgegeben wird, wenn auch ein lock auf dem speziell dafür vorgesehenen mutex besteht.
Würde ich das Speichern des Pointers erlauben, so könnte die Anwendung die Instanz nutzen, nachdem sie den Lock freigegeben hat.
Das Ganze ist sicherlich etwas übertrieben, da man auch undefinierbares Verhalten in der Dokumentation bescheinigen könnte, wenn dieser Fall eintritt, aber wenn es doch auch programmtechnisch lösbar ist, ist mir das immer lieber, als ein Verweis auf die Doku.Grüße
Timo
-
Wieso packst Du den Mutex nicht einfach mit in das Singleton-Objekt?
-
Tachyon schrieb:
Wieso packst Du den Mutex nicht einfach mit in das Singleton-Objekt?
Weil man den Lock beantragen muss, bevor man die Instanz bekommt.
(Falls das Deine Frage nicht beantwortet, habe ich sie nicht verstanden
)Grüße
Timo
-
horscht2999 schrieb:
Tachyon schrieb:
Wieso packst Du den Mutex nicht einfach mit in das Singleton-Objekt?
Weil man den Lock beantragen muss, bevor man die Instanz bekommt.
(Falls das Deine Frage nicht beantwortet, habe ich sie nicht verstanden
)Grüße
TimoDie als Singleton instanziierte Klasse wird doch bestimmt über irgendwelche Methoden angesprochen, oder?
Ich würde eher diese Methoden threadsafe machen.
-
horscht2999 schrieb:
Gibt es in C++ eine Möglichkeit zu verhindern, dass eine Methode mit Rückgabewert als rechte Seite einer Zuweisung verwendet wird?
Hallo Timo,
ich würde den Pointer auf Bar wrappen und den Wrapper in Foo private machen - so könnte das dann gehen:
#include <iostream> struct Bar { void freeTheWorld() { std::cout << "irgendwas" << std::endl; } }; class Foo { struct BarPtr { BarPtr( Bar* p ) : m_p( p ) {} Bar* operator->() { return m_p; } private: BarPtr& operator=( const BarPtr& ); Bar* m_p; }; static Bar m_myPrivateBar; public: static BarPtr getBar(/*...*/) { return BarPtr( &m_myPrivateBar ); } }; Bar Foo::m_myPrivateBar; int main() { //Foo::BarPtr _bar = Foo::getBar(/*...*/); //verboten: cannot access private struct declared in class 'Foo' Foo::getBar(/*...*/)->freeTheWorld(); //erlaubt return 0; }
-
horscht2999 schrieb:
Das Ganze soll ein Singleton Entwurfsmuster werden, bei dem die Instanz nur zurückgegeben wird, wenn auch ein lock auf dem speziell dafür vorgesehenen mutex besteht.
Gib ein Proxy Objekt zurück dass solange den lock hält solange es existiert.
dann kann ich zB den lock halten und 3 funktionen aufrufen anstatt 3mal den lock zu beantragen.
einzige gefahr ist, dass jemand den proxy irgendwohin kopiert und so den lock ewig hält.
das risiko lässt sich je nach anforderung noch reduzieren - aber generell denke ich wäre der ansatz ganz gut.
-
Tachyon schrieb:
Die als Singleton instanziierte Klasse wird doch bestimmt über irgendwelche Methoden angesprochen, oder?
Ich würde eher diese Methoden threadsafe machen.Die Methoden ansich sind auch treadsafe. Aber ich muss noch verhindern, dass jemand destroy_instance() aufruft, während ein anderer thread auf die Instanz zugreift. Deshalb zusätzlich noch der Lock für die Instanz.
Shade Of Mine schrieb:
Gib ein Proxy Objekt zurück dass solange den lock hält solange es existiert.
dann kann ich zB den lock halten und 3 funktionen aufrufen anstatt 3mal den lock zu beantragen.
einzige gefahr ist, dass jemand den proxy irgendwohin kopiert und so den lock ewig hält.
das risiko lässt sich je nach anforderung noch reduzieren - aber generell denke ich wäre der ansatz ganz gut.
Also derzeit muss der Lock nicht mehrmals angefordert werden. Es muss nur für jeden Methodenaufruf der Instanz die Instanz abgerufen werden. Den dazu nötigen lock, muss sich der thread nur einmal holen.
Wichtig war mir nur, dass der thread nicht auf die Instanz zugreifen kann, wenn er den lock freigegeben hat.Nochmals vielen Dank für die vielen Antworten, die ich weiß Gott nicht erwartet hätte. C++ hat mich mal wieder überzeugt, und ich werde mich wohl weiterhin mit dieser Sprache beschäftigen (zusätzlich zu dem Projekt, was gerade läuft
).Ciao
Timo