Vector und Singleton
-
Hi Leute,
kann es sein, dass wenn ich in einer Singleton-Klasse einen Vector als private Member-Variable benutzen will, diesen als static deklarieren muss?
Folgendes
class A : Singleton<A> { private: std::vector<int*> m_v; // ... };
hat bei mir nicht funktioniert, folgendes hingegen schon
class A: Singleton<A> { private: static std::vector<int*> m_v; // ... }; std::vector<int*> A::m_v;
Ist das wirklich so? Und worin liegt das begründet?
Danke. Mfg, smasher1985
-
Das hängt wohl sehr stark von der Implementierung des Singleton-Templates ab. Ohne zu wissen wie das aussieht kann man da schlecht was zu sagen.
MfG Jester
-
OK, dann hier meine Singleton-Template-Klasse:
template<typename T> class Singleton { static T* m_singleton; public: Singleton() { assert(!m_singleton); int offset = (int)(T*)1 - (int)(Singleton<T>*)(T*)1; m_singleton = (T*)((int)this + offset); } ~Singleton() { assert(m_singleton); m_singleton = 0; } static T& GetSingleton { assert(m_singleton); return *m_singleton; } static T* GetSingletonPtr { assert(m_singleton); return m_singleton; } }; template<typename T> T* Singleton<T>::m_singleton = 0;
Mfg, smasher1985
-
smasher1985 schrieb:
OK, dann hier meine Singleton-Template-Klasse:
int offset = (int)(T*)1 - (int)(Singleton<T>*)(T*)1; m_singleton = (T*)((int)this + offset);
Das sieht mir irgendwie hochgradig unportabel aus. Vermutlich zeigt der Zeiger danach einfach nicht auf die richtige Stelle und Du kannst daher nicht richtig auf Members zugreifen.
Caste doch einfach den this-pointer runter nach T* und zwar mit static_cast bzw. dynamic_cast oder sowas, dann sollte der Pointer an der richtigen Stelle sitzen und Du mußt nix mehr dran rumtunen.
Wobei ich nicht weiß, wie sicher das ist im Konstruktor so wild auf this rumzucasten, weil das SubObjekt noch nicht konstruiert ist. Alternativ könntest Du den this-Zeiger ja einfach als Parameter übergeben, dann müßtest Du allerdings einen eigenen Konstruktor für A schreiben, was Du ja offensichtlich vermeiden willst.
-
Diesen unportablen Trick hat er übrigens aus "Game Programming Gems"
-
na und
ich wußte bloß bisher nicth, dass das unportabel ist. Bisher war ich eigentlich zufrieden damit.
Aber hat das wirklich etwas mit meinem Problem zu tun? Ich glaube nicht, dass es daran liegt, dass der zeiger auf eine falsche stelle zeigt...
Mfg, smasher1985
-
Glauben kann man in der Kirche.
Probier doch einfach mal aus, ob es daran liegt. Ich sehe ansonsten keine prinzipiellen Probleme, warum es nicht gehen sollte.MfG Jester
-
Wofür ist dieser Trick denn eigentlich gut? Was macht er?
-
Diesen unportablen Trick hat er übrigens aus "Game Programming Gems"
Und der ist so schwachsinnig, dass mir während ich ihn las schwindelig wurde und ich das Buch sofort weglegen musste.
Ein simples:
m_singleton = static_cast<T*>(this);
hätte es auch getan. Ist aber halte nicht so "Game-Freak-Hacker-Star"-mäßig.
Was ich aber noch seltsamer finde ist Scott Bilas' (der Autor der Klasse) Begründung für den offset-Hack. So nach dem Motto: Es funktionierte alles nicht. Dann habe ich solange rumprobiert bis es auf meinem Compiler lief und dann habe ich nicht mehr drüber nachgedacht.
-
im OGRE Quellcode habe ich gerade gefunden:
00060 #if defined( _MSC_VER ) && _MSC_VER < 1200 00061 int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1; 00062 ms_Singleton = (T*)((int)this + offset); 00063 #else 00064 ms_Singleton = static_cast< T* >( this ); 00065 #endif
Wird bestimmt irgendeinen Sinn haben.
Vielleicht um einen Bug vom MSVC zu umgehen.
-
Mir heute nach noch irgendwann aufgefallen, daß es besser wäre den Konstruktor des Singleton-templates protected zu machen.
Das verhindert so schwachsinnige Dinge wie
Singleton<int> a;
oder auch
Singleton<VideoAdapter> Video;was ja offensichtlich nicht die gewünschte Verwendung der Klasse ist.
Außerdem sollte Singleton seinen Copy-Konstruktor und seinen operator= private deklarieren.Und so ein Teil steht wirklich in nem Buch drin??? Erschreckend!
MfG Jester