Instanzierung Funktions Üarameter



  • Hallo ich habe hier gerade im Forum so einen Quelltext gesehen.

    Meine Frage: Warum macht man eine Instanzierung im Funktions Parameter von void einfuegen ?

    class kartei{
      public:
        kunde * ersterKunde;
        void einfuegen (kunde * neuerKunde);
    
    };
    

    Da ich ich mit der oop noch nicht so viel beschäftigt habe sagte mir das nicht so viel also hab ich etwas rum experimentiert.

    So funktioniert es:

    #include <iostream>
    using namespace std;
    
    class kunde{
    
      public:
    
      void var();
    
    };
    
    void kunde :: var()
    {
     cout<<"TEST KUNDE" << endl ;
    }
    
    class kartei{
      public:
        kunde * ersterKunde;
        void einfuegen (kunde  *neuerKunde);
    
    };
    
     void kartei :: einfuegen (kunde *neuerKunde)
     {
       neuerKunde->var();
       cout<<"Kunde wurde angelegt"<<endl;
     }
    
    int main()
    {
    
    kartei a;
    
    a.einfuegen( NULL  );
    
    system("PAUSE");
    return 0;
    }
    

    Nun die Frage könnte man das ganze auch so machen:

    void kartei :: einfuegen (kunde neuerKunde)

    Also eine Instanzierung ohne den Pointer ( kunde *neuerKunde )



  • Es findet nirgendwo eine Instanzierung statt, wie kommst du auf diese Formulierung? Es wird lediglich ein Pointer herumgereicht, wo das Ding erzeugt wird weiß man nicht.
    In C hat man Zeiger übergeben, um teueres Kopieren der Parameter zu vermeiden. In deinem "Verbesserungsvorschlag" passiert nämlich folgendes: Der Compiler erzeugt eine Kopie des Kunden und ruft mit dieser Kopie die einfuegen Methode auf. Das kann teuer (im Sinne von zeitaufwändig) sein, wenn das Objekt groß ist und der Compiler viele Attribute kopieren muss. In C++ löst man das im Allgemeinen so:

    void einfuegen( const Kunde& Kunde )
    {
       ...
    }
    

    Edit:
    In deinem Beispiel hast du auch schon sehr schön die Fehleranfälligkeit der Originalmethode demonstriert. Eigentlich würde man erwarten, dass man einfuegen() immer mit einem gültigen Zeiger aufruft, weil es einfach keinen Sinn macht, einen nicht existierenden Kunden (Parameter = NULL) in eine Kartei aufnehmen zu wollen. Daher sollte man in der einfuegen() Methode noch prüfen, ob der Zeiger gültig ist. Bei der Verwendung einer Referenz übernimmt das der Compiler für dich, da eine Referenz niemals NULL sein kann.
    Als Faustregel sollte man für Parameter, die von der Programmlogik her notwendig sind, als Referenzen übergeben, während optionale Parameter als Zeiger übergeben werden sollten.

    Einfache Erklärung:
    Eine Referenz auf ein Objekt ist technisch so etwas wie ein Zeiger auf ein Objekt, nur dass dieser Zeiger immer gültig ist.

    Für eine detaillierte Erklärung von Referenzen besorge dir bitte ein C++ Buch und lies es dort nach, oder such´ im Web nach einer ausführlichen Erklärung.



  • Das hier ist doch eine Instanzierung oder nicht O_o

    kartei a;

    http://www.cpp-tutor.de/cpp/le09/klassen.html

    Kommen wir nun zum Begriff der Instanz. Eine Instanz ist prinzipiell nichts anderes, als die Realisierung einer Klasse. Dazu wird im Prinzip eine 'Variable' der entsprechenden Klasse definiert. Unter der OOP sprechen wir dann aber nicht von Variablen sondern von Objekten. Nehmen wir einmal an, Sie hätten eine Klasse Window definiert und folgende Anweisung geschrieben:Window myWindow;
    


  • Richtig, aber das hier instanziiert kein Objekt der Klasse Kunde, sondern einen Pointer, der auf ein Kunde-Objekt zeigt:

    Kunde *pKunde;
    

    Du hast in diesem Zusammenhang aber von Instanziierung eines Kunde-Objektes gesprochen, das meinte DocShoe.



  • Wurde ja eigentlich bereits ausführlich von DocShoe beantwortet.

    Natürlich könntest du dein Objekt direkt als Parameter übergeben (call-by-value), was letztendlich dann eine Kopie darstellt. Also muss der CopyKonstruktor von Kunde aufgerufen werden, alle Member werden kopiert (falls Kunde Pointer als Member besitzt solltest du nen eigenen Copy-Konstruktor definieren, da nur ein flat-copy stattfindet), beim Verlassen der Funktion einfügen muss der Destruktor für die lokale Kopie aufgerufen werden, etc.etc -- letztendlich geht die Performance also runter.

    Alternativ kannst du per Referenz übergeben, wie DocShoe auch dargestellt hat. Im Endeffekt arbeitest du dann mit einem Aliasnamen für das bereits existiernde Objekt. Man kann natürlich nur einen Alias von einem existierenden Objekt erstellen - deswegen ist die Referenz nicht NULL. Will man verdeutlichen, dass an dem Objekt keine Änderungen vorgenommen werden, setzt man ein const dafor (siehe wieder DocShoe). Das heisst im Umkehrschluss, dass du aber auch nur als const deklarierte Memberfunktionen des Objektes aufrufen kannst.

    edit: huch ich sehe gerade, dass ich NULL doch als Referenz vom Typ int übergeben kann 🙂


  • Administrator

    inter2k3 schrieb:

    edit: huch ich sehe gerade, dass ich NULL doch als Referenz vom Typ int übergeben kann 🙂

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-220511.html

    Grüssli


Anmelden zum Antworten