Pointer auf Klassenfunktionen



  • Hallo!

    Wie wäre es denn mit einem Interface? Du definierst Dir eine Klasse die (für Dein Beispiel) nur eine abstrakte Methode enthält. Objekte die diese Methode implementieren sollen werden von dieser Klasse (dem Interface) abgeleitet. Über einen Zeiger auf das Interface kannst Du die Methode dann ansprechen.

    Viele Grüße
    Thomas



  • Ja das Problem wäre dann nur, dass ich am Schluss meine Game Klasse etwa von 100 anderen ableiten müsste, nein ich denke, nicht dass dies eine Lösung wäre, aber danke dir trotzdem.

    Übrigens, ich suche nicht nach Alternativen, sondern ich möchte es wirklich so wie im source - code machen. Es geht nur um das korrekte Type - Casting...



  • Ishildur schrieb:

    Ich interessiere mich für den technischen Hintergrund der Programmarchitektur des Delphi - Framework, welches auch in der VCL von Borland verwendet wird.

    Naja, Delphi ist eine andere Sprache, da kannst du nicht erwarten, dass es in C++ genauso funktioniert. Beim Borland C++ Builder funktioniert es zwar genauso, aber die haben ihren Compiler dementsprechend erweitert. In "reinem" C++ muss man das mit Templates lösen.

    Hier hast du was zu lesen: http://www.gotw.ca/gotw/083.htm

    Ich würde aber die Interface-Variante nehmen.



  • Ishildur schrieb:

    Ja das Problem wäre dann nur, dass ich am Schluss meine Game Klasse etwa von 100 anderen ableiten müsste

    100? Was soll die Klasse denn alles für Events verarbeiten? Da würde ich mich eher ranmachen und das Design nochmal überdenken.



  • Nein nein, da hast du was falsch verstanden!
    Die Keyboard Klasse wäre ja nur eine von sehr sehr vielen Klassen, die Events versenden würde...

    Ich versuche meine Frage etwas allgemeiner zu Formulieren:
    Unter C wird oft mit Callback Funktionen gearbeitet. Was ich möchte, wäre eine Callback Funktion, die aber eine Memberfunktion einer Klasseninstanz sein kann.

    Oder Stell dir mal folgendes vor:

    // ******************** Konventionell ********************
    class Tetris{
    public:
    bool isThereABlockImpact(void)
    };

    Tetris t1,t2;
    while(true){
    if(t1.isThereABlockImpact() || t1.isThereABlockImpact()) DoSomething();
    }
    // *******************************************************

    // ****************** Meine Architektur ******************
    class Tetris{
    public:
    void (*onBlockImpactAction)(Tetris *pTetris);
    };

    onBlockImpact(Tetris *pTetris){
    DoSomething();
    }

    Tetris t1,t2;
    t1.onBlockImpactAction = t2.onBlockImpactAction = onBlockImpact;
    // *******************************************************

    Die gesammte WinApi, sowie viele Bereiche der DirectX Api funktionieren nach diesem Prinzip. Ich möchte nun noch einen Schritt weitergehen, indem ich innerhalb der Callback funktionen auch auf Membervariablen von Klasseninstancen zugreifen kann...



  • Ishildur schrieb:

    Unter C wird oft mit Callback Funktionen gearbeitet. Was ich möchte, wäre eine Callback Funktion, die aber eine Memberfunktion einer Klasseninstanz sein kann.

    Ja, schon klar. Aber so einfach ist das nicht, da Memberfunktionen beim Aufruf an ein Objekt gebunden sind.
    Schau dir den Link an, den ich dir gegeben habe.



  • Templates kommen für mich leider nicht in Frage, da dies eine Bibliothek wird, die in einer DLL ausgeliefert werden soll...

    Du hast geschriben, eine memberfunktion sei an ein Objekt gebunden. Technisch gesehen ist sie doch nur an einen 32 - Bit Wert gebunden, und mit einem reinterpret_cast sollte es doch nicht allzuschwer sein das ganze zu casten.

    Ich meine folgendes geht ja auch:

    struct Point{
     int xPos,yPos;
    };
    
    struct Dimension{
     int xDir,yDir;
    };
    
    int main(){
     Point p = {5,15};
     Dimension *pDim = reinterpret_cast<Dimension*>(&p);
     std::cout << pDim->xDir;
    };
    

    Also muss mann doch so etwas auch mit einer Memeberfunktion machen können ?? 😕



  • theoretisch.
    eine memberfunktion bekommt immer als unsichtbares argument den this zeiger mitübergeben. sie zu casten wäre also gleich(ähnlich)bedeutend damit, folgendes zu tun:

    void foo (int) {}
    void bar (double,double) {}
    
    int main () {
       void (*a) (int) = reinterpret_cast<void(*)(int)>(&bar);
       (*a)(10); //bar erwartet aber 2 argumente.
    }
    

    damit wird die funktion sehr unwahrscheinlich funktionieren, auch wenn nur ein typ eines parameters geändert wird. der compiler sieht da aber keinen unterschied.
    womöglich gibt es aber sogar welche, die das zulassen.
    ich bezweifle außerdem, dass der code durch solche dinge einfacher und wartbarer wird.



  • Verstehe nicht wo das Problem mit den Templates ist, die gibts ja nur in einer kleinen Callback-Klasse. Deine Library kann ja weiterhin in einer DLL stehen.

    Dieses rumgecaste ist doch alles nicht das wahre.



  • Ein Methodenzeiger in Delphi sind eigentlich zwei Zeiger, einer auf eine Instanz und einer auf eine Methode. Ein C++-Elementfunktions"zeiger" kann alles Mögliche sein und ist deshalb nicht einmal implizit nach void* konvertierbar, auf jeden Fall aber wird kein Objekt mitgespeichert. Die beiden funktionieren technisch also völlig verschieden.
    Wenn du eine Delphi-ähnliche Lösung suchst, kommt boost::function von www.boost.org dem Ganzen sehr nahe, hat vielleicht sogar mehr Vorteile (man kann es an beliebige Funktoren, also auch globale Funktionen binden) als Nachteile (auf 10 Parameter beschränkt, evtl. langsamer?). Um eine Elementfunktion als ein Callback zu binden, das als boost::function gespeichert wird, kannst du dann boost::mem_fn oder boost::bind verwenden.


Anmelden zum Antworten