Pointer oder Referenzen bei Übergabeparameter?



  • GPC schrieb:

    Neku schrieb:

    chrische5 schrieb:

    Also ich mach es auch wie Volkard, weil ich bei Funktion, die ein Parameter ändert dann immer & davorschreiben muss und somit gearnt bin: Aha, die Funktion ändert den Parameter.

    Darum gibt es ja das kleine aber feine Schlüsselwort "const" 😉 Wenn ein "const" vor dem Parameter steht, wird dieser nicht verändert - kann man ja auch gar nicht.

    Wäre ich paranoid oder bösartig, könnte ich das const mit const_cast einfach wegcasten und fröhlich das Objekt verändern :p 😉

    Wieso braucht eine Programmiersprache eigentlich ne "Kindersicherung"? Man sollte meinen, es seien Vernünftige Menschen am Werk.. :p 😉



  • Ich halt es so:

    Referenzen da wo geht,
    Pointer da wo man referenzen nicht nutzen kann.

    Faelle wo Referenzen nicht so geeignet sind:

    - wenn man nen explizieten nicht definiert / nicht gueltig Wert braucht ... (NULL Pointer)
    - Wenn ich extensiv caste. Geht zwar prinizipiell auch mit referenzen, aber gefuehlsmaessig nehm ich da doch lieber pointer. (denk mal haengt eher damit zusammen das man bei nem logischen cast gern mal nen ungueltigkeitswert haett, also eher siehe punkt 1)
    - referenzen kann man ned in standardcontainer pappen ... da muss man pointer nehmen ....

    Ciao ...



  • Wo ich keinen Weg mit Referenzen sehe: bei der Behandlung polymorpher Objekte



  • 1310-Logik schrieb:

    Eine "gute" Funktion/Methode sollte nicht einen Übergabeparameter verändern dürfen. Ergebnisse sollten nur mit return zurückgegeben werden.

    Das halte ich für nicht konsequent umsetzbar. Was machst Du, wenn eine Methode mehrere Parameter ändern muss?

    Ich halte es so, wie viele bereits gesagt haben:
    - wenn nichts geändert wird: const-Referenz
    - wenn nichts geändert wird, aber eine Referenz nicht geht, aus welchem Grund auch immer: const-Pointer auf const-Daten
    - wenn geändert wird: Referenz
    - wenn geändert wird, aber Referenz nicht geht, aus welchem Grund auch immer: Pointer (wobei da noch zu überlegen ist, ob der Pointer const deklariert wird und nur die Daten nicht const sind)

    Wobei ich alle Fälle schon einsetzen musste.

    1310-Logik schrieb:

    Wieso braucht eine Programmiersprache eigentlich ne "Kindersicherung"? Man sollte meinen, es seien Vernünftige Menschen am Werk..

    Ich sehe das const eher als eine Hilfestellung, die dem Benutzer einer Methode sagt, diese Parameter werden von der Funktion geändert und diese eben nicht. Umgehen kann man alles, auch an eine private-deklarierte Klassenvariable kommt man von außen heran, wenn man will.



  • Cosmixx schrieb:

    1310-Logik schrieb:

    Eine "gute" Funktion/Methode sollte nicht einen Übergabeparameter verändern dürfen. Ergebnisse sollten nur mit return zurückgegeben werden.

    Das halte ich für nicht konsequent umsetzbar. Was machst Du, wenn eine Methode mehrere Parameter ändern muss?

    Ein Tupel zurückgeben. Gut, in C++ ist das mit einer nicht sehr schönen Syntax verbunden. In anderen Sprachen (wohl hauptsächlich funktionalen) ist es aber gang und gäbe.



  • 1310-Logik schrieb:

    Wo ich keinen Weg mit Referenzen sehe: bei der Behandlung polymorpher Objekte

    😕

    Nochmal zur Erinnerung, zum Speichern sind Referenzen sowieso nicht gemacht.



  • .filmor schrieb:

    1310-Logik schrieb:

    Wo ich keinen Weg mit Referenzen sehe: bei der Behandlung polymorpher Objekte

    😕

    Nochmal zur Erinnerung, zum Speichern sind Referenzen sowieso nicht gemacht.

    Ich meinte zB beim Observer Pattern. Wie willst du da ne Referenz übergeben?

    virtual void update( Subject* subject )
    {
        Foo* foo = dynamic_cast< Foo* >( subject );  //Foo ist abgeleitet von Subject (Abstrakte Klasse)
        foo->doBar();
    }
    


  • Mit dem dynamic_cast setzt du dich ja auch eigentlich über das Konzept der Polymorphie hinweg, normale virtuelle Methoden funktionieren mit Referenzen ohne Probleme.

    Btw, so gehts auch mit Referenzen:

    virtual void update( Subject& subject )
    {
        Foo* foo = dynamic_cast< Foo* >( &subject );
        foo->doBar();
    }
    

    😉



  • Ja, aber doBar() ist eine Methode von Foo, nicht von Subject, also muss ich ja casten.
    So sieht doch die "offizielle" Implementierung vom Observer aus?
    Warum denn nun Referenzen?



  • [edit] war Blödsinn [/edit]

    Greetz, Swordfish



  • 1310-Logik schrieb:

    Ja, aber doBar() ist eine Methode von Foo, nicht von Subject, also muss ich ja casten.
    So sieht doch die "offizielle" Implementierung vom Observer aus?

    virtual void update( Subject* subject )
    {
        Foo* foo = dynamic_cast< Foo* >( subject );  //Foo ist abgeleitet von Subject (Abstrakte Klasse)
        foo->doBar();
    }
    

    Was ist denn das für eine Implementierung des Observer-Patterns?
    Wenn Du in der update-Methode ein Subject als Pointer übergibst, kannst Du den doch nicht in der Methode pauschal zu einem Typ einer abgeleiteten Klasse casten.





  • Ah, ok, wenn Du das als Beispiel nimmst, dann ist klar. Gefällt mir aber designtechnisch nicht.



  • Cosmixx schrieb:

    Das halte ich für nicht konsequent umsetzbar. Was machst Du, wenn eine Methode mehrere Parameter ändern muss?

    diesen designfehler jagen, ihn umzingeln und vernichten natürlich.



  • volkard schrieb:

    diesen designfehler jagen, ihn umzingeln und vernichten natürlich.

    😃 Na das will mich mal sehen in einem realen Projekt.

    Ich habe nicht gesagt, dass es ein Designfehler ist, falls Du das mit dem auffallend fett gedrucktem Wort sagen willst ;). Mir gefällt es nur nicht.
    Das Beispiel ist in jedem Fall eine gängige Observer-Pattern-Implementierung. Trotzdem kann man das mit dem Casten in einen abgeleiteten Typ vermeiden.
    Btw, nicht bei jeder Observer-Implementierung muss man den this-Pointer des Subjekts weitergeben oder?



  • Cosmixx schrieb:

    Das Beispiel ist in jedem Fall eine gängige Observer-Pattern-Implementierung. Trotzdem kann man das mit dem Casten in einen abgeleiteten Typ vermeiden.

    Wie würdest Dus im Getreide Beispiel lösen?

    Cosmixx schrieb:

    Btw, nicht bei jeder Observer-Implementierung muss man den this-Pointer des Subjekts weitergeben oder?

    Wenn Du mehrere Subjekte beobachtest, und wissen willst, von welchem die Nachricht ist, dann schon.



  • Seit wann kann man mit dynamic_cast keine Referenzen casten ??

    virtual void update( Subject& subject ) 
    { 
        Foo& foo = dynamic_cast< Foo& >( subject );  //Foo ist abgeleitet von Subject (Abstrakte Klasse) 
        foo.doBar(); 
    }
    


  • Hat mich auch schon gewundert dass das keiner einwendet 😉

    Dabei weiss doch jeder, dass ein dynamic_cast auf Referenzen einen bad_cast werfen kann, während der auf Pointern einen Nullzeiger zurückliefert, wenn's nicht stimmt 🤡



  • Cosmixx schrieb:

    volkard schrieb:

    diesen designfehler jagen, ihn umzingeln und vernichten natürlich.

    Ich habe nicht gesagt, dass es ein Designfehler ist

    aber ich. zeig mir mal ne anwendung für wo zwei returnwerte benötig werden. ich müßte lange in der krimskramskiste suchen.



  • 1310-Logik schrieb:

    Wenn Du mehrere Subjekte beobachtest, und wissen willst, von welchem die Nachricht ist, dann schon.

    Das ist mir bewusst. Man kann das Casten aber auch vermeiden, durch eine Art Objekt-ID, die über eine virtuelle Methode abgerufen wird oder über RTTI.

    Die Referenz auf das Subjekt ist außerdem hinfällig, wenn man dieses nicht zum updaten braucht, z.B. wenn die Daten von ganz woanders herkommen, im einfachsten Fall aus einer Singleton-Datenklasse.

    1310-Logik schrieb:

    Wie würdest Dus im Getreide Beispiel lösen?

    Man sollte zumindest in der update-Methode überprüfen, ob der dynamic_cast erfolgreich war. Wobei wir wieder beim Ausgangsthema wären: Wenn man nämlich das Subjekt als Pointer übergibt, liefert dynamic_cast NULL zurück und bei einer Referenz wird eine Exception geworfen.

    Für das kleine Beispiel, dass der Veranschaulichung dient, ist es aber ok so.

    volkard schrieb:

    zeig mir mal ne anwendung für wo zwei returnwerte benötig werden. ich müßte lange in der krimskramskiste suchen.

    Achso das meinst Du. Es ging doch darum, dass eine Anwendung keinen Übergabeparameter ändern sollte und Ergebnisse nur über return zurückgeben sollte. IMHO kann man das nicht durchziehen. Ich hab hier grade einen Nachrichtengenerator für Nachrichten, die über Sockets versendet werden. An die übergebe ich nen BYTE-Pointer, der mit dem Inhalt der Nachricht gefüllt wird und einen integer, der die Länge der Nachricht erhält. Sind schonmal 2 Parameter.


Anmelden zum Antworten