-> Operator bei Zeigern



  • Hey ihr,

    Habe eben gelernt, dass der -> Operator immer dann verwendet wird, wenn man auf Attribute und Funktionen eines Objektes zugreifen möchte und dabei als Name einen Zeiger verwendet.

    In beispielsweise dem Borland C++ Builder wurde der -> Operator immer verwendet um beispielsweise die Eigenschaft eines Buttons zu ändern.
    Warum greift man nie direkt auf diese Objekte zu, sondern benutzt die Zeiger überhaupt?
    Was Zeiger allgemein genau in diesem Zusammenhang bringen verstehe ich nicht.

    cya
    David



  • Normalerweise muß man Zeiger dereferenzieren, bevor man auf ihre Member zugreifen kann - das sieht dann so aus: (*ptr).member (* hat geringere Priorität als . und muß geklammert werden). Weil diese Schreibweise unmöglich aussieht, wurde der Pfeil als "Abkürzung" dafür eingeführt.



  • Das was du meinst ist C++/CLI, aber es trifft ja auch auf c++ und die meisten anderen Programmiersprachen zu, die objektorientiert arbeiten. Also 1. Zeiger finde ich überflüssig und werden auch fast gar nicht mehr in .Net genutzt(Es gibt kleine ausnahmen). Der -> sagt das du von einer Instanz auf ein Member oder Werte zugreifen willst. Und es sind keine Zeiger in .Net es soll nur den umstieg für den C++ler erleichtern, das er denkt er arbeite da mit Zeigern 😉



  • Helfender Helfer schrieb:

    Das was du meinst ist C++/CLI, aber es trifft ja auch auf c++ und die meisten anderen Programmiersprachen zu, die objektorientiert arbeiten. Also 1. Zeiger finde ich überflüssig und werden auch fast gar nicht mehr in .Net genutzt(Es gibt kleine ausnahmen). Der -> sagt das du von einer Instanz auf ein Member oder Werte zugreifen willst. Und es sind keine Zeiger in .Net es soll nur den umstieg für den C++ler erleichtern, das er denkt er arbeite da mit Zeigern 😉

    Was für eine Menge an Unfung.

    • Nein, er meinte nicht C++/CLI, er meinte Borland. Wieso sollten dort, Deiner Meinung nach, keine Zeiger für Objekte verwendet werden?!

    • Zeiger sind alles andere als überflüssig. Dort, wo sie bei Borland gebraucht werden (GUI-Programmierung) sind sie unumgänglich.

    • Fast *alles* in .NET wird über Zeiger gemacht.

    • Doch, es sind Zeiger in .NET. Was denn sonst? Ziegen?



  • Ich dacht immer es wären Referenzen...
    aber belehre mich eines anderen 🙂 ich zog mich da auf Visual Studio nicht auf den Borland...



  • Helfender Helfer schrieb:

    Ich dacht immer es wären Referenzen...
    aber belehre mich eines anderen 🙂 ich zog mich da auf Visual Studio nicht auf den Borland...

    Ja, aber der Erstposter nunmal auch Borland...

    In C# und Java etc. wird unter der Oberfläche recht intensiv gebrauch von Zeigern gemacht, auch wenn es anders genannt wird und sich nach Außen als Objektzugriff verbirgt.

    Davon abgesehen sind Zeiger in C++ meines erachtens unablässig in der dynamischen Speicherverwaltung.

    777 schrieb:

    In beispielsweise dem Borland C++ Builder wurde der -> Operator immer verwendet um beispielsweise die Eigenschaft eines Buttons zu ändern.
    Warum greift man nie direkt auf diese Objekte zu, sondern benutzt die Zeiger überhaupt?
    Was Zeiger allgemein genau in diesem Zusammenhang bringen verstehe ich nicht.

    Die VCL (oder wie nun die Borlandbibliothek heißt) arbeitet sehr stark mit Zeigern, ich schätze mal weil die Masken etc. dynamisch zur Laufzeit aufgebaut werden. Ansonsten wäre es imho auch schwerer schon zur Designtime dir die Maske anzuzeigen.

    cu André



  • Achso... mhh kay..
    Aber es ginge auch ohne.
    Also könnte ich jetzt zum Beispiel, wenn ich selbst ein Formuar mit der Windows API programmieren will.... einfach in Dev C++ ... das ganze anders Regeln und direkt auf den Button als Objekt zugreifen.
    Ich versteh den Sinn von Zeigern noch immer nicht... und ich versteh auch nicht zu 100% den Unterschied zwischen Zeigern und Referenzen, welche ja bei Abstrakten Klassen eine Rolle spielen...-.- und wo ich auch den Sinn versteh 😉

    cya
    David



  • 777 schrieb:

    Aber es ginge auch ohne.
    Also könnte ich jetzt zum Beispiel, wenn ich selbst ein Formuar mit der Windows API programmieren will....

    Naa toll, da hast Du Handles, die auf die Objekte zeigen, das ist konzeptuell auch nichts anderes als Zeiger.



  • 777 schrieb:

    Ich versteh den Sinn von Zeigern noch immer nicht... und ich versteh auch nicht zu 100% den Unterschied zwischen Zeigern und Referenzen, welche ja bei Abstrakten Klassen eine Rolle spielen...-.- und wo ich auch den Sinn versteh 😉

    cya
    David

    referenzen sind kastrierte Zeiger, alles was die Referenz kann, kann der Zeiger schon lange, nur die schreibweise ist anders (-> statt .), also auch das mit den abstrakten klassen.

    Der zeiger kann aber etwas was die Referenz nicht kann,

    *int p = 17;
    cout << *(p+1) << endl;
    

    hier wird versucht das was im Speicher neben dem inhalt von p steht als integer zu interpretieren. Kann und sollte wenn es im debugmodus Übersetzt wurde zum Programmabsturz führen, wenn der Speicher nie reserviert wurde.



  • Nun kann man ja auch nicht nur Variablen definieren, sondern gleich ganze Objekte.
    Im Buch werden diese als dynamische Variablen bezeichnet.

    int *i = new int(2); //Int, was mit 2 initialisiert wurde
    int *i =  new int; //Int, was nicht initialisiert wurde.
    

    Nun gibt es hier auch nur einen Zeiger auf ein Namenloses Int-Objekt.

    int i = new int(2);
    

    dagegen funktioniert nicht.
    Obwohl es viel sinnvoller wäre...-.-

    cya
    David



  • Ein "int i" ist ja auch kein Zeiger, sondern ein reiner int-wert - und den kannst du einfach mit "int i=2;" initialisieren (ohne new).



  • Ja, frage soll nur sein, was das überhaupt bringt, so einen Zeiger auf ein int-Objekt zu machen.

    Oder es gibt ja auch:

    int *i = 2;

    Zulässig aber sinnfrei...-.- und im Buch der Kerl ist ganz begeistert davon und benutzt das nur.

    cya
    David



  • Sag blos, das gibt's wirklich? Nach meinem Kenntnisstand ist das ein Syntax-Fehler (oder zumindest undefiniert). Einem Zeiger kannst du nur eine legale Adresse (egal ob die von new geliefert wurde oder zu einer existierenden Variablen gehört) oder 0 zuweisen.



  • Im Buch steht das so... und der Compiler schluckt es.
    Allerdings verstehe ich einfach den Sinn von allgemein Zeigern nicht.
    Genau wie der Sinn von Referenzen mir noch leicht verschleiert ist 😃
    Ich würde einfach Objekte, ihre Namen.
    Variablen, ihre Namen definieren und dann darüber auch drauf zugreifen und sie verändern, wies gut ist.

    Naja... und in Zeigern sehe ich einfach keinen Sinn und warum die überhaupt immer verwendet werden.
    cya
    David



  • Referenzen sind Alias-Bezeichnungen für Variablen, die irgendwo anders im Programm existieren (durch die Parameterübergabe per Referenz kannst du z.B. direkt mit der Variable im Hauptprogramm hantieren).

    void per_val(int i)
    {
      i=5;
    }
    
    void per_ref(int& i)
    {
      i=5;
    }
    
    int main()
    {
      int i=10;
      cout<<"Start:    "<<i<<endl;//Ausgabe 10
      per_val(i);
      cout<<"value:    "<<i<<endl;//immer noch 10
      per_ref(i);
      cout<<"reference:"<<i<<endl;//nun 5
    }
    

    Pointer enthalten Speicheradressen, an denen sich andere Variablen befinden können - oder auch dynamisch angelegte Speicherbereiche ( int*i=new int[10]; enthält die Adresse eines 10 Felder großen int-Arrays).



  • 777 schrieb:

    ...

    int i = new int(2);
    

    dagegen funktioniert nicht.
    Obwohl es viel sinnvoller wäre...

    Nein !
    =>

    777 schrieb:

    ...Allerdings verstehe ich einfach den Sinn von allgemein Zeigern nicht....

    Stimmt ! 😉

    777 schrieb:

    ...Ich würde einfach Objekte, ihre Namen.
    Variablen, ihre Namen definieren und dann darüber auch drauf zugreifen und sie verändern, wies gut ist....

    Und wie würdest Du das machen:

    void setzeString(string s) {
       s = "777";
    }
    
    int main() {
       string mainString;
       setzeString(mainString);
       return 0;
    }
    

    ?

    Es hilft Dir für mainString überhaupt nichts, dass in s in setzeString() geändert wird, weil es ja zwei verschiedene Objekte sind.

    Oder wenn Objekte mit anderen verknüpft werden sollen:

    struct Person {
       string name;
    };
    
    struct KFZ {
       KFZ(Person bes): besitzer(bes) {}
       string modell;
       Person besitzer;
    };
    
    int main() {
       Person Simon;
       Simon.name = "Simon Meyer";
       KFZ bmw(Simon);
       KFZ audi(Simon);
       KFZ mofa(Simon);
    
       // Simon heiratet und ändert seinen Nachnamen:
       Simon.name = "Simon Mueller";
    
       // wem gehören jetzt die KFZs ?
    ...
    

    Genau für sowas braucht man außer "Objekten" noch "Verweise" ... und die sind in C++ eben als Referenzen und Zeiger angeboten.

    Mal eine Frage: In welcher Programmiersprache hast Du bislang programmiert ?

    Gruß,

    Simon2.



  • Mal eine Frage: In welcher Programmiersprache hast Du bislang programmiert ?

    Bislang habe ich C# meistens gemacht oder einfach mit Borland Buttons geklickt.

    Doch das hat mir nicht gefallen, weil ich zwar so tolle Programme schreiben konnte, jedoch von den untersten Grundlagen eigentlich keine Ahnung hatte.
    Somit habe ich mir den C++ Primer geschappt um C++ mal von Grund auf zu lernen.

    Naja... und da kommt es jetzt teilweise zu verständnisproblemen.

    Aber was dein erstes Beispiel angeht:
    Dort bringen Zeiger wirklich etwas.

    Doch eigentlich bringen sie auch nur ein bisschen, weil man die Funktion einfach innerhalb von main() definieren könnte und alles ginge wieder ohne die Zeiger 😛

    cya
    David



  • 777 schrieb:

    Doch eigentlich bringen sie auch nur ein bisschen, weil man die Funktion einfach innerhalb von main() definieren könnte und alles ginge wieder ohne die Zeiger 😛

    Erstens kennt C++ keine lokalen Funktionen (d.h. du kannst nichts "innerhalb von main()" definieren) und zweitens besteht die Stärke von Referenz-Parametern dahinter, daß du bei jedem Aufruf neu entscheiden kannst, welche Variable an den Parameter gebunden wird.



  • Habe mal das Programm von CStoll nachprogrammiert:

    #include <iostream>
    #include <vector>
    using std::cout;
    using std::endl;
    using std::vector;
    using std::cin;
    void veraendere_zahl(int);
    void veraendere_zahl_wirklich(int);
    int main() 
    { 
       int hallo = 10;
       cout << hallo << endl;
       veraendere_zahl(hallo);
       cout << hallo<< endl;
       veraendere_zahl_wirklich(hallo);
       cout << hallo << endl;
       getchar();   
    }
    void veraendere_zahl(int hallo)
    {
       hallo = 20;   
    }    
    void veraendere_zahl_wirklich(int &hallo)
    {
       hallo = 20;   
    }
    

    Meine Fragen zu dazu wären, dass es doch nicht geht eine Funktion mit übergebenem Wert auszugeben, die garkeinen Rückgabewert hat.
    Hier habe ich nun zuvor die Funktion aufgerufen und dann den neuen 'hallo' ausgegeben.

    Dennoch meldet der Compiler auch in diesem Programm einen Fehler:

    [Linker error] undefined reference to `veraendere_zahl_wirklich(int)'

    cya

    David



  • 777 schrieb:

    Meine Fragen zu dazu wären, dass es doch nicht geht eine Funktion mit übergebenem Wert auszugeben, die garkeinen Rückgabewert hat.
    Hier habe ich nun zuvor die Funktion aufgerufen und dann den neuen 'hallo' ausgegeben.

    Du gibst die Funktion doch gar nicht aus 😉

    Dennoch meldet der Compiler auch in diesem Programm einen Fehler:

    [Linker error] undefined reference to `veraendere_zahl_wirklich(int)'

    Ja, der Prototyp sollte auch zur tatsächlich definierten Funktion passen, sonst hast du Probleme (die Lösung heißt "veraendere_zahl_wirklich(int**&**);").


Anmelden zum Antworten