Rückgabe von Objekten



  • Hallo Freunde,

    hat jemand zufällig mal ein Beispiel wie man ein Objekt aus einer Funktion heraus sauber zurückgeben kann?
    Gehts so ?:

    Connection function(int param) {
      Connection con; // 'con'-objekt vom 'Typ' Connection
      con.server("heise.com");
      return con; // Rückgabe hier ok?
    }
    

    geht sowas?

    ➡ der behaarte bueffel bedankt sich.

    ciao bueffel



  • eher nicht. denn mir fällt keine sinnvolle kopiersemantik für Connections ein. vermutlich hat die klasse Connection daher keinen kopierkonstruktor.

    Connection con=connect("www.heise.de");//nee
    
    Connection con("www.heise.de");//jo
    
    Connection con;
    con.connect("www.heise.de");//sieht man auch
    


  • bueffel schrieb:

    hat jemand zufällig mal ein Beispiel wie man ein Objekt aus einer Funktion heraus sauber zurückgeben kann?
    Gehts so ?:

    Connection function(int param) {
      Connection con; // 'con'-objekt vom 'Typ' Connection
      con.server("heise.com");
      return con; // Rückgabe hier ok?
    }
    

    Rein vom Prinzip her okay, dir muss nur bewusst sein das du eine Kopie zurücklieferst (Das lokale Objekt wird beim verlassen zerstört, die Rückgabe gibt ein mittels Kopierkonstruktor angelegtes Objekt zurück - Vorausgesetzt der Compiler kann hier nicht optimieren).



  • d.h. ich kann überhaupt kein objekt der klasse zurückgeben!?
    ohwe...
    auch nicht wenn ichs mit new probiere und nen zeiger aufs objekt zurückgebe oder so?

    // edit:

    Rein vom Prinzip her okay, dir muss nur bewusst sein das du eine Kopie zurücklieferst (Das lokale Objekt wird beim verlassen zerstört, die Rückgabe gibt ein mittels Kopierkonstruktor angelegtes Objekt zurück - Vorausgesetzt der Compiler kann hier nicht optimieren).

    ok dann mit new und zeiger rückgabe. dann wirds ja nicht mehr zerstört beim verlassen des stackframes.



  • bueffel schrieb:

    d.h. ich kann überhaupt kein objekt der klasse zurückgeben!?

    bei den allermeisten klassen gehts. aber File, Process, Connection, World und noch ein paar sachen sind sinnvollerweise nicht kopierbar.

    auch nicht wenn ichs mit new probiere und nen zeiger aufs objekt zurückgebe oder so?

    klar geht das.
    dabei bleibt's ja *ein* objekt und es muß keine kopie gebaut werden.



  • joa dann machts so mehr sinn.
    einfach n zeiger nutzen.

    Connection* function(int param) {
           Connection *con;
           con->server("sex.com");
           return con;
    }
    


  • Connection* function(int param) {
           Connection *con=new Connection;
           con->server("google.com");
           return con;
    }
    


  • jo das natürlich noch besser.
    glaub das hat ja was zutun mitm default ctor.



  • bueffel schrieb:

    jo das natürlich noch besser.
    glaub das hat ja was zutun mitm default ctor.

    kaum. ja, er wird bei der aktion aufgerufen, aber darum gehts nicht.

    ohne das siehts so aus:

    Connection* function(int param) { 
           Connection *con=675;//zufälliger inhalt
           con->server("sex.com"); 
           return con; 
    }
    

    und auf adresse 675 im speicher darfst du gar nicht zugreifen. dein programm stürzt ab.
    mit new besorgst du dir den speicher.

    Connection *con=675;//zufälliger inhalt
    con=new Connection;
    

    jetzt zeigt con auf guten speicher, wo du auch draf arbeiten darfst.



  • hm. stimmt okay. irgendwie logisch.
    du kannst gut erklären, danke! 🙂

    ich hab mal gelesen von einer objekterzeugung wo man direkt aufn default ctor drauf zugreift und von einer wo man das nicht tut. irgendwie so gabs da mal was. bin vergesslich lol 🙂


  • Administrator

    Gäbe ja eigentlich noch eine weitere Möglichkeit, erst recht bei Objekten, welche nicht kopierbar sind:

    void function(Connection& con, int param)
    {
      // Wähle dank param was aus, oder was du auch mit param machen willst.
      con.server("google.com");
    }
    
    // ... irgendwo, wo du die Funktion aufrufst ...
    Connection con;      // erstelle das Objekt
    function(con, 645);  // übergib das Objekt zur Bearbeitung.
    

    Grüssli



  • Dravere schrieb:

    Gäbe ja eigentlich noch eine weitere Möglichkeit, erst recht bei Objekten, welche nicht kopierbar sind:

    Connection con;      // erstelle das Objekt
    function(con, 645);  // übergib das Objekt zur Bearbeitung.
    

    die viel sicherer, weil da kein speicherloch entstehen kann, weil man das zugehörige delete nicht vergessen kann.

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.


  • Administrator

    volkard schrieb:

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.

    Kann man das sofort erkennen? Was ist, wenn das folgende als Funktionsprototyp steht:

    void function(Connection const* con, int param);
    

    Ich finde so einen Code eher fehleranfällig und unhandlich, erst recht um die Funktion zu implementieren, da man eine Fehlerbehandlung einführen muss, falls ein Null-Zeiger übergeben wird. Und was für einen Fehler macht man dann? Assertion, Exception, Return Wert, ignorieren?

    Wenn man ein gültiges Objekt übergeben muss, dann sollte man wohl bei einer Referenz bleiben. So muss der Aufrufer dafür sorgen, dass immer ein gültiges Objekt kommt, wodurch dieser womöglich optimieren kann, da er weiss, dass nie ein ungültiges Objekt übergeben wird. Dadurch fällt die ganze Fehlerbehandlung weg.

    Grüssli

    PS: Sorry, wenn das ein wenig ins Off-Topic geht. Aber ich wäre noch gespannt auf eine Antwort darauf. 🙂



  • volkard schrieb:

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.

    Nachteil hierbei ist aber das eine NULL-Prüfung erfolgen muss, die wieder zu einem Fehler führen kann.

    Ich für meinen teil ziehe hier entweder:
    a) Die Referenzübergabe (Da keine Null-Werte zulässig)
    oder
    b) Eine Rückgabe eines Smartpointers (Freigabe geregelt)
    vor.

    cu André



  • Dravere schrieb:

    da man eine Fehlerbehandlung einführen muss, falls ein Null-Zeiger übergeben wird.

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.


  • Administrator

    volkard schrieb:

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.

    Wieso soll das logisch sein? Wenn ein Zeiger erwartet wird und wir nicht in C sind, dann ist es für mich logisch, dass man auch einen Nullzeiger übergeben kann.

    Und über dass assert(con) wird sich der Benutzer freuen, wenn zur Laufzeit ein Fehler passiert, weil er dachte, dass man auch einen Nullzeiger übergeben darf.
    Noch lustiger wird es, wenn im Debugmodus irgendwie der Fehler nie erreicht wurde, da immer ein gültiges Objekt übergeben wurde. Release erstellt, an den Kunden ausgeliefert. Der Arbeitet und plötzlich -> Fatal Error oder sonst ein Fehler, da auf einen Nullzeiger zugegriffen wurde. Alle Daten verloren ...

    Grüssli



  • volkard schrieb:

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.

    Nein, Ein Zeiger impliziert auch das man 0 verwenden darf.
    Ich schaue doch nicht in die Implementierung um zu sehen ob 0 zulässig ist oder nicht. Bei der Referenzübergabe geht es garnicht anders, und hier muss man nur die Deklaration kennen um sauber zu programmieren!

    cu André



  • asc schrieb:

    Nein, Ein Zeiger impliziert auch das man 0 verwenden darf.

    nö. die spracher erlaubt es. aber das ist auch schon alles.
    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?



  • volkard schrieb:

    nö. die spracher erlaubt es. aber das ist auch schon alles.
    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?

    Keine Ahnung, da ich C-Funktionen nur dann einsetze wenn C++ wirklich ein Flaschenhals in der Anwendung ist, oder begrenzt an DLL-Schnittstellen. Und ersteres habe ich bislang nur äußerst selten im Praxiseinsatz erlebt.

    P.S: Und Diskussionen über C-Schnittstellen wären glaube ich eher im C-Forum passend, oder?


  • Administrator

    volkard schrieb:

    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?

    Wenn ich da auch noch was hinzufügen darf neben den Argumenten von asc.
    Seit wann hat die Sprache C:
    a) Referenzen? Daher ist es ziemlich witzig, dass du eine C Funktion nennst.
    b) Klassen? Man kann einen String in C gar nicht anders als über einen Zeiger implementieren.

    Wie es asc gesagt hat, wir sind hier im C++ Forum.

    Grüssli



  • sie schmiert ab. und das ist nicht schlimm. so grobe programmierfehler muss keiner fangen.


Anmelden zum Antworten