Pointer einer ObjektMethode



  • Hallo,

    ich habe eine Frage, und zwar habe ich ein SDK, dass in einer Funktion eine Methode entgegennimmt, um von diesem aus, später Objekte zu erzeugen.

    Beispiel

    class Foo
    {
        Foo()
        {
          /***/
        }
    
        static Foo* Alloc()
        {
           return new Foo();
        }
    }
    
    /**/
    Register(..., Foo::Alloc, ...)
    

    Ist es möglich Daten in einem Objekt zu speichern und eine nicht-statische Methode des Objektes anzugeben? Eventuell hat einer eine Idee was ich falsch mache?

    class Foo
    {
        Foo(void* p)
        {
          /*...irgendwas...*/
        }
    
        static Foo* Alloc(void* p)
        {
           return new Foo(p);
        }
    }
    
    class Temp
    {
       private:
           void* mein_ptr;
    
        Temp(void* p)
        {
           mein = p;
        }
    
        Foo* Get()
        {
           return Foo::Alloc(mein_ptr);
        }
    }
    
    /**/
    Temp* f = new Temp(mein_ptr);
    Register(..., f->Get, ...)
    

    Ich versuche also sozusagen Daten zu speichern, damit er diese mit dem Argument aufruft, also sozusagen einen Wert den ich später im Konstruktor benutzen kann. Da ich jedoch die Funktion "Register" nicht verändern kann, und er nur FUNC() aufruft ohne Argumente habe ich gedacht, baue ich mir eine Hiflsklasse..

    Leider sagt er die ganze Zeit: Cannot pass <unkown_type>. Hat einer eine Idee?

    Ich danke euch...



  • Nein. Das ist so nicht möglich, weil die Funktionssignatur nicht stimmt. Im ersten Moment sieht das hier:

    f->Get()
    

    Zwar richtig aus, ist es aber nicht, weil du da ja nicht f->Get() als Funktion angibst, sondern das Resultat, was eine Funktion vom Typ:

    Foo* (*) (void*)
    

    ist. Aber einen vom Typ:

    Foo* (*) ()
    

    erwartet wird.

    Als alternativen würde ich da entweder einen Standardkonstruktor nehmen, oder was Wohl ev. besser ist einen statischen Wert für alle Klassen, welchen du dann jeweils ändern kannst und als Standardparameter übergeben wird.

    struct Foo
    {
        Foo ( void* v ){}
        static Foo* Alloc()
        {
           return new Foo(v_);
        }
    
        static void* v_;
    }
    void* Foo::v_ = 0;
    
    class Foo
    {
        Foo( int i = 2) // Defaultinitialisierung
        {
          /***/
        }
    
        static Foo* Alloc()
        {
           return new Foo();
        }
    }
    

    Wobei ich mal annehme, dass die Defaultinitialisierung nicht so ganz das ist, was du willst. Also würde ich die erste Variante nehmen und dann den statischen Wert verändern, wenn du einen anderen benötigst.

    Foo::v_ = 2;
    Register(..., &Foo::Alloc, ...)
    


  • Hi!

    Ich danke dir. Und was würdest du mir empfehlen wenn ich mehrere Werte brauche? Bei der statischen Behandlung kann ich ja nur einen Wert setzen. Selbst wenn ich eine liste hätte mit seperaten Einträgen, würde ich beim Standardaufruf der einfachen Alloc() Funktion nicht wissen welchen Eintrag ich brauche 😕

    Ich danke dir.



  • DonnerCobra schrieb:

    Hi!

    Ich danke dir. Und was würdest du mir empfehlen wenn ich mehrere Werte brauche? Bei der statischen Behandlung kann ich ja nur einen Wert setzen. Selbst wenn ich eine liste hätte mit seperaten Einträgen, würde ich beim Standardaufruf der einfachen Alloc() Funktion nicht wissen welchen Eintrag ich brauche 😕

    Ich danke dir.

    Ich glaube ich weiss, was du willst. Du willst bei jedem Objekt, dass für dich erzeugt wird die Konstruktorparameter selber bestimmen, ja?
    Warum glaubst du denn, dass du das brauchst? Weil das ist so direkt nicht so einfach umzusetzen und wahrscheinlich auch nicht nötig..



  • Hi!

    Weil ich eine Skriptsprache implementiert habe. Also nötig ist es auf jeden Fall, dass ich nachträglich einen Pointer mitübertragen muss.

    Ich weiß nicht ob das den Rahmen sprengen würde. Also, die Skriptsprache leitet auf die Registerfunktion weiter. Dort nehme ich einen Parameter entgegen.

    Ich habe also auch eine Klasse gewrappt, und aus dem Parameter aus dem ich letztlich mit zwei anderen Befehlen eine instanz dieser Klasse erstellen kann, die müsste ich halt weiterleiten an den Konstruktor um die Klasse entsprechend darauf vorzubereiten.

    Hast du eine Idee wie ich es eventuell angehen könnte?

    Danke dir..



  • Ich bin mir nicht ganz sicher, was du haben willst. Bring mal ein "konkreteres" Beispiel.
    Wenn es immernoch nach dem obigen Schema geht, kannst du ja einfach den statischen Parameter vor jeder Erzeugung so ändern, wie er sein soll.

    Foo::v_ = 2;
    lib_ruf_meine_funktion_auf (); // irgendwo wird dann new obj (v_) aufgerufen
    Foo::v_ = 5;
    lib_ruf_meine_funktion_auf ();
    

    Wenn die lib da nichts anderes anbietet und ich dein Problem richtig verstehe musst du halt so einen Umweg gehen..



  • HI!

    Ich probiers es nochmal 🙂 Also, ich habe ein SDK was die Register() Methode enthält, und der Code ist closed, also den Inhalt der Register Methode kann ich nicht ändern.

    Die Registermethode bekommt also eine Methode, die das Programm aufrufen kann, WENN es ein Objekt der Klasse braucht.

    Beispiel

    class meinTest : public NodeData{
    
         static NodeData* Alloc()
         {
             return new meintest;
         }
    
    }
    
    Dann registrieren mit     Register(meinTest::Alloc)
    

    Soweit so gut, jedoch wird die Funktion ohne Parameter aufgerufen. Mein Ziel ist es, das ich IRGENDWIE einen Parameter an diese Funktion übergeben kann, egal wie, denn wenn ich 10 Klassen habe, die ein Objekt darstellen und das Programmm mal dies, oder mal das braucht, dann kann ich das nicht nach einer Liste machen, weil das ja vorher nicht absehbar ist welches Objekt er haben will.

    Es ist ein echt "einfaches Problem", aber die Lösung ist wahrscheinlich nicht vorhanden, oder?

    danke....



  • Ich verstehe immernoch nicht ganz, für was du den Parameter brauchst.

    Wie ich das verstehe willst du sowas machen:

    class meinTest : public NodeData{
    
         static NodeData* Alloc( int id)
         {
             if (id == 2)
                return new meintest;
             if (id == 5)
                return new foo;
             ...
         }
    }
    

    Wenn dem so ist. Kannst du nicht einfach mehrere Funktionen registrieren?



  • Hi!

    Exakt, genau sowas bräuchte ich, irgendwie bräuchte ich einen parameter.
    Jetzt das Problem. Die Registermethode gehört ja zum closed SDK und ruft nur "()" ohne Parameter auf.

    Deswegen suche ich ja eine Möglichkeit irgendwie ein Argument mit zu übergeben, was ursprünglich ja gar nicht vorgesehen ist.

    Bis dann..



  • DonnerCobra schrieb:

    Deswegen suche ich ja eine Möglichkeit irgendwie ein Argument mit zu übergeben, was ursprünglich ja gar nicht vorgesehen ist.

    Bis dann..

    Ok. Dann haben wir jetzt einen Ansatz. Aber was ich nicht verstehe, WO willst du einen Parameter übergeben? In welchen Situationen? (Ich bin immernoch der Meinung, dass du das halt über ne statische Variable machen kannst, die dir das "aktuelle" Objekt anzeigt. Weil du kannst eine Funktion ja nur einmal regestrieren und dann läuft das ganze. Du brauchst dementsprechend einen weiteren Anhaltspunkt, wann welches Objekt gebraucht wird und da änderst du halt dann die statische Variable. Fertig.



  • Es erscheint mir, als wenn du gegen die Bibliothek arbeitest und nicht mit der Bibliothek.

    Wenn kein Parameter vorgesehen ist, ist das Konzept anscheinend, dass die erzeugende Funktion (Foo::Allloc) entweder Default-Objekte konstruiert oder z.B. nach dem Prototype-Pattern.

    Die konkrete Initialisierung findet woanders statt. Irgendwoher muss der "Erzeuger" ja auch wieder wissen, wie er die Objekte zu erstellen hat. Das bedeutet wiederum - wenn du diese Parameter gezielt manipulieren kannst - dass du auch den Zeitpunkt des Aufrufs genau kennst.



  • Hi!

    Es ist nicht unbedingt der Standard Konstruktor nötig. Was ich dem Konstruktor übergebe, ist ja egal, das entscheide ich selbst in Alloc(). Nur die Funktion selbst wird ohne Parameter aufgerufen, und das ist gegen die Bibliothek, da hast du Recht.

    Aber was danach passiert, ist egal, da kann ich tun was ich will. Da könnte ich rein theoretisch auch das Programm beenden.

    Ich hatte halt gehofft, das ich irgendwie einen Parameter mit übergeben kann, dass ich in der Alloc Methode entgegennehmen kann.

    Bye 🙂



  • DonnerCobra schrieb:

    Hi!

    Es ist nicht unbedingt der Standard Konstruktor nötig. Was ich dem Konstruktor übergebe, ist ja egal, das entscheide ich selbst in Alloc(). Nur die Funktion selbst wird ohne Parameter aufgerufen, und das ist gegen die Bibliothek, da hast du Recht.

    Aber was danach passiert, ist egal, da kann ich tun was ich will. Da könnte ich rein theoretisch auch das Programm beenden.

    Ich hatte halt gehofft, das ich irgendwie einen Parameter mit übergeben kann, dass ich in der Alloc Methode entgegennehmen kann.

    Bye 🙂

    Es geht nicht darum, ob du das darfst, es geht darum, ob das Sinn macht, was du machst. (Kann es durch aus..)
    Aber lies mal meinen Post nochmal durch. Ich will auf etwas ganz anderes raus. Mehr auf die Frage, was würdest du machen, wenn du Zugriff auf die Funktion hättest und selber bestimmen kannst?

    Das Problem ist ja, dass die Funktion dir ein Objekt erstellt, welchem du gerne einen Parameter zur Initialisierung übergeben würdest.

    so etwas:

    createObject (2);
    createObject (5);
    ...
    

    Nur dein Problem ist, dass du createObject keinen Parameter übergeben kannst, respektive die lib das für dich macht. Nun hast du aber ja das gleiche Problem, wenn du das selber machen musst, musst du wissen, WANN du WAS übergeben willst. Und das kannst du äquivalent zu dem gewünschten Beispiel oben machen, indem du einfach die statische Var änderst. (es gibt sicher noch andere Wege. Das ist imho einfach der offensichtlichste).

    static_var = 2;
    createObject (); // lib ruft das auf
    static_var = 5;
    createObject ();
    ...
    

Anmelden zum Antworten