Klassenfrage :)



  • @omggg
    Um etwas genauer zu sein:
    Es gibt die Klasse Display mit Methoden um in den FB zu Zeichnen und zu Schreiben. Ausschließlich ein Objekt dieser Klasse wird einem Objkt klasse ui_interface übergeben das sich selbst darüber darstellt. Das Objekt der Klasse ui_interface wird einem Objekt der Klasse Apple Übergeben das die berechnung der Mandelbrodtmenge durchführt und diese über die Methode "ui_interface->diplay->putPixel" darstellt. Die Parameter der Berechnung ist das Objekt ui_interface. Und auch die Buttons sind in ui_iterface. Dort genau komme ich nicht weiter, eine Apple->Methode aufrufen wenn in ui-interface::onMouseOver x und y passen. (Die Mausfunktion ist nicht das Problem sondern der Methodenaufruf)



  • @SeppJ
    Danke für die Antwort, aber ich steige leider nicht dahinter was die Definition von Caller bedeuted. Wie du selbst schon andeutest ist das ziemlich umständlich.


  • Mod

    Ist nur ein Beispiel für die beiden Modi, die ich erklärt habe:

    • unbound_foo_member ist ein Zeiger auf eine Methode der anderen Klasse Foo und der Nutzer dieses Zeigers muss selber irgendwo ein Foo-Objekt herbekommen (hier erstellt der Caller dafür das Objekt mit i=123)
    • bound_member ist ein allgemeiner Zeiger auf eine beliebige Funktion (mit der passenden Signatur), und man hat ihm hier ein funktionsartiges Objekt zugewiesen, das den Aufruf an das Foo-Objekt (i=456) aus der main koppelt. Man kann dem gar nicht mehr ansehen, dass das irgendwie mit Foo zu tun hat, es ist nicht unterscheidbar von einem normalen Funktionszeiger (außer dass der Typ dahinter irgendetwas wildes ist)

    Dass ich das in die Klasse Caller verpackt habe, kommt wegen deiner Fragestellung, dass du das unbedingt einer Klasseninstanz übergeben wolltest. Das Prinzip ist aber völlig unabhängig davon, wie man es benutzt. void (Foo::*)(void) mag zwar kompliziert aussehen, aber ist auch nur ein Typ wie jeder andere Variablentyp und nutzt sich genauso wie int.

    Ich möchte aber nochmals betonen, dass das äußerst ungewöhnlich ist, so viel (oder überhaupt irgendetwas) in C++ mit Memberfunktionszeigern machen zu wollen, und du dein Design nochmal überdenken solltest. In C kann ich das ja noch sehen (und da sind es ja auch keine richtigen Memberfunktionen), um so etwas wie virtuelle Funktionen zu emulieren. Ist es vielleicht das, was du wirklich willst? Virtuelle Funktionen? Und hast noch nicht davon gehört weil du neu in C++ bist?

    omggg ist unser örtlicher Dauertroll. Ich würde an deiner Stelle dessen Beiträge einfach komplett ignorieren.



  • @SeppJ
    Haha, immerhin half mir der Troll meine Frage etwas zu konkretisieren.
    Ich meine: Ist es möglich Apple->schrumpf() aus Apple->Wurm->friss() aufzurufen? und, würdest du bitte eine der beiden Möglichkeiten nochmals isoliert für mich dartellen, wenn nicht gar die Antwort auf die Frage?
    Ich verstehe vor allem die Definition Von Caller(...) unter public nicht


  • Gesperrt

    @EL-europ
    Ich bin kein Programm, aber @SeppJ mag mich nicht, deshalb schreibt er oder sie das.

    Auf deine Fragen kann ich zurzeit aber nicht näher eingehen.



  • @omggg
    ok, danke



  • @SeppJ Ichversuch mal deinen Code zu beschreiben
    in der Klasse Caller
    wird mit "void (foo.." ein Zeigerobjekt auf irgendeine Methode der Klasse Foo angelegt,
    und mit "std::func.."eine std::function mit dem namen "bound_member" und dem Rückgabewert void deklariert.
    Dann unter public folgt der Konstruktor von Caller dem zwei Parameter und dazu zwei ppassende Standartwerte übregeben werden? Und in der Methode call() wird "einfach" auf den Konstruktor von Foo zugegriffen um dann über das Objekt f.*unbound_foo_member auf eine in den Konstrutionsparametern übergebene Funktion in Foo zugreifen zu können und dann wird die std::function bound_member aufgerufen.

    Wenn das stimmt ist das mir zu Abtrakt um es auf Apfel und Wurm übertragen zu können.
    Kannst du bitte den Konstruktor von Caller( wenn es den überhaupt einer ist) und die "Schritte" in main näher erläutern


  • Mod

    Da, ganz ohne drumherum.

    #include <iostream>
    #include <functional>
    
    
    using namespace std;
    
    
    class Foo
    {
    	int i;
    public:
    	Foo(int i) : i(i) {}
    	void func1() { std::cout << "Func 1 von Foo(i=" << i << ")\n"; }
    };
    
    
    int main()
    {
    	Foo f(456);
    	std::function<void()> bound_func1 = [&f] {f.func1(); };
    	void (Foo::* unbound_func1)() = &Foo::func1;
    	
    	bound_func1();
    	(f.*unbound_func1)();
    }
    

    Den Caller hatte ich doch nur gezeigt, weil du dich so daran aufgehangen hattest, dass das unbedingt in einer Klasse sein müsse, als ob da dran irgendetwas besonderes wäre.



  • @SeppJ
    Ich hab eine einfache Frage ja auch kompliziert gestellt, und versuch jetzt erstmal die Übertragung deines Codes


  • Mod

    @EL-europ sagte in Klassenfrage 🙂:

    @SeppJ
    Ich hab eine einfache Frage ja auch kompliziert gestellt, und versuch jetzt erstmal die Übertragung deines Codes

    Nein! Werd' lieber dein Design los, das dich denken lässt, dass dies überhaupt nötig wäre! Du übersiehst garantiert irgendwas simples, das schon in der Sprache eingebaut ist. Dazu musst du natürlich erst einmal die Sprache besser lernen. Aber das wäre was gutes, denn man sollte schließlich die Sprache beherrschen, die man spricht.



  • @SeppJ
    Mir fällt nix besseres ein. Ich müsste ja eigentlich eine "abstrakte" Klasse definieren von der ich Apfel und Wurm gemeinsam ableite; Wenn ich den oop-ansatz richtig verstehe?


  • Mod

    @EL-europ sagte in Klassenfrage 🙂:

    @SeppJ
    Mir fällt nix besseres ein. Ich müsste ja eigentlich eine "abstrakte" Klasse definieren von der ich Apfel und Wurm gemeinsam ableite; Wenn ich den oop-ansatz richtig verstehe?

    Da wird ja gerade der Designfehler sein, denn das klingt offensichtlich falsch. Aber mit dem Apfel-Wurm-Beispiels kommt man da nicht weiter, weil da in der echten Welt keine tiefergehenden Beziehungen existieren, als das beides physikalische Objekte sind, und das ein Apfel einen oder mehr Würmer haben kann. In der echten Welt wird der Apfel nie etwas mit einem Wurm machen, und die Würmer werden eventuell etwas aus dem umgebenden Apfel fressen. Nichts davon klingt auch nur entfernt nach Übergabe von Memberfunktionszeigern..



  • @SeppJ Nun ja aber:
    Die Beziehung "Apfel->schrumpf() wenn Apfel->Wurm->friss()" ist gegeben.
    Aber du hast Recht, ich sollte zumindest die entsprechenden Kapitel noch mal lesen. Bis dahin 🙂


  • Mod

    Ist ein bisschen komisch, dass der Apfel sich von dem Wurm fressen lässt, aber naja, nehmen wir das mal als gegeben an, weil die Analogie vielleicht nicht perfekt ist. Aber wieso muss in dem Fall an Wurm::friss die Methode Apfel::schrumpf übergeben werden? Sollte nicht die Fressmethode wissen, dass sie den Apfel schrumpfen soll?

    class Wurm
    {
        void friss(Apfel &zu_fressender_apfel)
        {
            ...
            zu_fressender_apfel.schrumpf();
            ...
        }
    };
    

    Oder ist die Sache, dass der Wurm auch in anderem Obst sein kann? Dann wäre das, wie spekuliert, ein Fall für virtuelle Methoden:

    class Obst
    {
        virtual void schrumpf();
    };
    
    class Apfel: public Obst
    {
        virtual void schrumpf() {wie ein Apfel schrumpft;}
    };
    
    class Birne: public Obst
    {
        virtual void schrumpf() {wie eine Birne schrumpft;}
    };
    
    class Wurm
    {
        void friss(Obst &zu_fressendes_obst)
        {
            ...
            zu_fressendes_obst.schrumpf();
            ...
        }
    };
    

    Da wird dann in friss automatisch an die passende schrumpf-Methode verwiesen, je nachdem, welches Obst der Wurm frisst.

    Im Hintergrund arbeiten dann zugegebenermaßen Memberfunktionszeiger. Aber das macht halt die Sprache für dich als Feature, und du musst dich nicht mit solch fehleranfälligem Zeug mit komischer Syntax herumschlagen. In C muss man das halt selber machen, wenn man diesen Effekt will, daher hatte ich die Vermutung, dass das hier die Richtung ist, aus der du kommst.



  • Danke @SeppJ
    Ich habs über std::function hinbekommen die Methode aufzurufen, jetzt kann ich den restlichen Code erstma debuggen 😋



  • @EL-europ sagte in Klassenfrage : ):

    Und werde die entsprechenden Kapitel in Jürgen Wolf's c++11 lesen. Oder gibt es eine Onlninefom die vielleicht sogar besser ist.
    Herr Wolf ist in diesem Buch immer sehr theoretisch mit seinen Beispielen.

    Du hast den schlechtesten Autor für C++ erwischt: WARNUNG: Bücher von Jürgen Wolf zu C und C++ zum Lernen ungeeignet weil....

    Wenn du englisch beherrschst, dann verwende LearnCpp.


  • Mod

    Ojeh, das hatte ich ganz überlesen. Das erklärt die komisch klingenden Designprobleme. Laut Jürgen Wolfs Designbeispielen ist ein Supermarkt schließlich ein Wurstbrot. Nein, das ist kein Scherz.



  • @Th69 Danke für den Link



  • @SeppJ @Th69
    Ich glaube Herrn Wolf fehlte damals (als er die Bücher schrieb) einfach die Praxis, also nicht "Programmierpraxis" sondern Berufspraxis. Seine Beispiele lesesn sich wie von einem Schüler dessen Lebensmittelpunkt die Schule ist. Es sind seit dem "c++11" schon Jahre vergangen, und zu hoffen das Jürgen Wolf seine Prxis erweitert hat und in Bücher einbringen wird ist berechtigt.


  • Gesperrt

    Hm, nur weil in einem Beispiel ein Supermarkt ein Wurstbrot ist... sollte man ihm vielleicht nicht jegliche Fähigkeiten absprechen, geradeaus zu denken... Denn das Supermarktbeispiel ist total irrelevant... wichtig sind die Paradigmen.