Methodenzeiger -> Laufzeitfehler



  • Hallo Leute,

    möchte gerne meinen Code ungefähr in der folgenden Art und Weise realisieren:

    // Klasse UserInterface
    class UserInterface
    {
    public:
    	UserInterface(void);
    	~UserInterface(void);
    
    	void Action();
    }
    
    UserInterface::UserInterface()
    {
    	Button* b = new Button(&UserInterface::Action); // <- Runtime Error
    }
    
    // Klasse Button
    class Button
    {
    public:
    	Button(void);
    	Button(void (UserInterface::*click)());
    	~Button(void);
    
    private:
    	void (UserInterface::*on_click)();
    }
    
    Button::Button(void (UserInterface::*click)())
    {
    	on_click = click;
    }
    

    Leider bekomme ich hierbei immer einen Laufzeitfehler:

    Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

    Was mache ich falsch? 🙂

    Vielen Dank euch schon einmal 🙄



  • Was soll das denn machen? Du übergibst die Adresse einer Funktion, oder wie?

    UserInterface::UserInterface()
    {
        Button* b = new Button(&UserInterface::Action); // <- Runtime Error
    }
    


  • Du willst wohl so etwas, wie das hier:

    #include <iostream>
    #include <string>
    
    class class1
    {
    public:
    	void ausgabe ()
    	{ 		
    		std::cout << "Funktion Klasse 1" << std::endl;
    	}
    };
    
    class class2
    {
    public:
    	void ausgabe2 () 
    	{
    		std::cout << "Funktion Klasse 2" << std::endl;
    	}
    };
    
    class button
    {
    public:
    	template<class t> void  click (t* pt,void (t::* f)() ) { (pt->*f) ();} 
    };
    
    int main()
    {
    	class1 g;
    	class2 h;
    
    	button b;
    
    	b.click (&g, &class1::ausgabe);
    	b.click (&h, &class2::ausgabe2);
    
    	return 0;
    }
    


  • dust schrieb:

    Was soll das denn machen? Du übergibst die Adresse einer Funktion, oder wie?

    Ganz genau. 🙂

    drakon schrieb:

    Du willst wohl so etwas, wie das hier:

    Najaaa... Nicht ganz. Mir ist nicht ganz klar, wofür ich jetzt Templates nutzen sollte, und um den Aufruf des Funktionspointers gehts ja auch (noch) nicht.

    Was ich möchte, ist eigentlich einfach genau folgendes:

    Klasse A erstellt in ihrem Konstruktor ein Objekt von Klasse B und übergibt dabei dem Konstruktor von Klasse B eine Adresse auf eine Memberfunktion von Klasse A. Klasse B soll dann diese Adresse in einer privaten Membervariable von sich abspeichern.

    Also mein obiger Code kompiliert ja anstandslos (also der vollständige 😉 ), aber es gibt halt diesen blöden Laufzeitfehler... Die Frage ist also: Was ist daran (so, wie er ist) falsch? 😕

    mfg



  • An dem Code ist an sich nichts fehlerhaftes. Der Fehler liegt woanders.



  • Bloops schrieb:

    ...

    Mir fehlt bei dem Ganzen noch der Instanzzeiger, oder habe ich etwas übersehen (Ein Methodenzeiger auf eine nicht-statische Funktion erfordert neben den Funktionszeiger auch noch den Instanzzeiger...).



  • asc@ausgeloggt schrieb:

    Mir fehlt bei dem Ganzen noch der Instanzzeiger, oder habe ich etwas übersehen (Ein Methodenzeiger auf eine nicht-statische Funktion erfordert neben den Funktionszeiger auch noch den Instanzzeiger...).

    Den braucht man beim Aufruf, klar. Den sehe ich hier aber noch nicht, demnach dürfte hier nix krachen.


  • Mod

    Falls das mit Visual C++ passiert: benutz mal zum Testen die Compilerschalter /vmg und /vmv mit dem gesamten Projekt.



  • camper schrieb:

    Falls das mit Visual C++ passiert: benutz mal zum Testen die Compilerschalter /vmg und /vmv mit dem gesamten Projekt.

    Ich werd irre 😃 Jezz gehts... Woher soll man als Normalsterblicher so etwas wissen? 😮

    Tausend Dank. Nur /vmg scheint übrigens zu reichen, da /vmv ja anscheinend der def-wert ist. Irre.

    thx a lot


  • Mod

    Das ist so eine von den Compilererweiterungen, für die Visual C++ berüchtigt ist - diese Optimierung ist für sich genommen gar nicht so schlecht, aber es wäre schön, wenn es sich nicht um eine Standardeinstellung handelte, schließlich ist dieses Verhalten auch nicht standardkonform. Wenn möglich, solltest du dafür sorgen, dass die Klasse UserInterface definiert wurde, bevor die Klasse Button definiert wird (Im Grundsatz: Jede Klasse sollte definiert sein, bevor ein Objekt eines Zeigers auf eine Memberfunktion dieser Klasse definiert wird - das ist fast immer möglich). Dann bedarf es keiner besonderen Compilereinstellungen, was nur von Vorteil sein kann.



  • camper schrieb:

    Jede Klasse sollte definiert sein, bevor ein Objekt eines Zeigers auf eine Memberfunktion dieser Klasse definiert wird - das ist fast immer möglich). Dann bedarf es keiner besonderen Compilereinstellungen, was nur von Vorteil sein kann.

    Jo, habe es jetzt auch ohne die Compilereinstellung hinbekommen. Viele Dank Dir noch einmal.


Anmelden zum Antworten