Wenn ich virtuelle Methode aufrufe kracht es
-
Selbst wenn es eine Singleton-Klasse sein soll, arbeitet man dann nicht auf pThis sondern ruft pThis->methode() auf und macht methode() nicht-statisch.
Statische Methoden haben gefälligst nicht auf Instanzobjekten zu arbeiten. Da würde ich keine minute auf Fehlersuche verschwenden, solange ich so einen Murks mache.
-
Versuch mal sowas:
class my_singleton { private: my_singleton() { } my_singleton &instance() { static my_singleton me; return me; } void do_method() { // Code } public: static void method() { instance().do_method(); } };
-
Ja? Und wo muss ich jetzt deswegen Instanzmethoden statisch machen und die dann über me irgendwas ändern lassen?
Das muss man nie machen. Methoden, die das Objekt benutzten haben nicht statisch zu sein und trotzdem im Objekt rumzupfuschen. Es gibt sowas wie den Grundsatz, undurchsichtige Seiteneffekte und unnötige Fehlerquellen zu vermeiden.
-
Das Problem ist, dass die Funktion gleichzeitig auch eine Callbackfunction ist und da kommst du nicht mit Methoden weiter (Beschwerden bitte an MS).
Jedoch ist ein gobaler Pointer nicht die Lösung. Such mal nach SetWindowLong und GetWindowLong, damit kannst du ein 32 Bit Wert mit einem HWND assosiren. Setzt den einfach auf this und dann ist das Problem mit den mehreren Instancen gelöst.
Nun vergiss mal WM_CREATE und setzt den Code dochthin wo er hingehört, das heist hinter den CreateWindow-Aufruf im Konstruktor.
Wenn dies nicht dein Problem löst, dann musst du woll noch etwas konkreter werden.
-
Es gibt auch Methodenpointer. Außerdem kann man (wenn es schon ne statische Methode sein muss) immer noch die Instanz als Parameter übergeben. Aber heimlich was über pThis zu ändern ist sicherlich kein gutes Design und endlose Quelle für mögliche hard-to-find Bugs.
-
Optimizer schrieb:
Es gibt auch Methodenpointer. Außerdem kann man (wenn es schon ne statische Methode sein muss) immer noch die Instanz als Parameter übergeben. Aber heimlich was über pThis zu ändern ist sicherlich kein gutes Design und endlose Quelle für mögliche hard-to-find Bugs.
Sagte ich nicht Beschwerden an MS? Jendenfals helfen Methodenpointer hier nicht weiter da die WinAPI einen Funktionspointer haben will/muss, und mit ein Methodenpointer ist kein Funktionspointer wegen der heimlichen übergabe von this als Parameter.
-
und mit ein Methodenpointer ist kein Funktionspointer wegen der heimlichen übergabe von this als Parameter
in der winapi faq ist ein ansatz, mit dem genau das möglich ist.
-
Ich hab den 4 Seiten Thread einmal überflogen und eine Schlussfolgerung konnte ich nicht erkennen. Aber wer umbedingt den this pointer als this Pointer vorliegen haben will, also wem dieser Syntaxzucker nicht völlig schnuppe ist kann das so machen:
class BaseWindow{ private: static LRESULT CALLBACK DummyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static void RegisterClass(); HWND hWnd; public: BaseWindow(); ~BaseWindow(); virtual LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); }; void BaseWindow::RegisterClass() { static bool registered = false; if(!registered) { registered = true; //register } } BaseWindow::BaseWindow() { RegisterClass(); hWnd = CreateWindow(..., this); } BaseWindow::~BaseWindow() { DestroyWindow(hWnd); } LRESULT CALLBACK BaseWindow::DummyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { Window*wbWin = (Window*)GetWindowLong(hwnd, GWL_USERDATA); if(wbWin != NULL) return wbWin->WndProc(hwnd, msg, wParam, lParam); else return DefWindowProc(hwnd, msg, wParam, lParam) } LRESULT BaseWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { //sämtliche Member wie gewohnt zugänglich switch(msg) { ... } }
-
erinnert mich irgendwie an eine Klasse, die ich mal im winapi teil gepostet hab:
class SubClass{ private: static long BaseWindowProc(HWND hwnd,unsigned int message,unsigned int wParam,unsigned int lParam){ callback oldCallback=reinterpret_cast<callback>(GetProp(hwnd,"oldCallback")); SubClass* callingClass=reinterpret_cast<SubClass*>(GetProp(hwnd,"this")); return callingClass->WindowProc(oldCallback,hwnd,message,wParam,lParam); } HWND subWindow; callback oldCallback; protected: virtual long WindowProc(callback oldCallback,HWND hwnd,unsigned int message,unsigned int wParam,long lParam)=0; public: SubClass(HWND window):subWindow(window){ if(!window){ throw(Exception::CreationFailed("couldn't create subclass->Nullpointer",__LINE__,__FILE__)); } //get old callback oldCallback=reinterpret_cast<callback>(GetWindowLongPtr(subWindow,GWLP_WNDPROC)); //set properties SetProp(subWindow,"oldCallback",oldCallback); SetProp(subWindow,"this",this); //set new callback SetWindowLongPtr(subWindow,GWLP_WNDPROC,reinterpret_cast<long>(BaseWindowProc)); } virtual ~SubClass(){ //reset window SetWindowLongPtr(subWindow,GWLP_WNDPROC,reinterpret_cast<long>(oldCallback)); RemoveProp(subWindow,"oldCallback"); RemoveProp(subWindow,"this"); } HWND getHandle(){ return subWindow; } };
nachteil deiner Klasse: sie kann die funktionalität eines buttons(zb) nicht erhalten.
Das Klassendesign hab ich aber dann verworfen,da es einige probleme damit gab, zb, dass man in teufelsküche kam,wenn man versuchte eine subclass mit dem von Gethandle gelieferten HWND zu erstellen. Die Designschwäche war stark genug, dass ich mich davon wieder abgewandt hab(auch wenn es möglich wäre,das design zu korrigieren,es lohnt nicht, der aufwand wird viel zu groß,und das ganze endet in lustigen undurchsichtigen rekursionen)
-
Danke für eure Antworten.
Ich werd mal einiges probieren.