Komische Sache mit Doppelpointern
-
Hallo,
ich hab diesmal ein Problem mit Pointern. Gegeben sind zwei Klassen
class Typ { string name; bool setName( string newName ) { //Auf gültigkeit prüfen... this->name = newName; return true; } string getName() { return this->name; } }; class TypListe { vector<Typ*> typen; //... int gibTyp( size_t id, Typ* t ) { if( id >= this->typen.size() ) return -1; if( this->typen[id] == NULL ) return -2; t = this->typen[id]; return 0; } int gibTyp( string name, Typ* t ) { size_t i_max = this->typen.size(); for( size_t i = 0; i < i_max; ++i ) { if( this->typen[i] == NULL ) continue; if( this->typen[i]->getName() == name ) { t = this->typen[i]; return 0; } } return -1; } };in der Klasse TypListe habe ich eine Methode, um mir den Zeiger eines Types zurückgeben zu lassen, indem ich der Methode den Namen des Types gebe.
Eine Ähnliche Methode macht das selbe, nur nicht mit dem Namen des Types, sondern mit der ID des Types in der Liste.Hier mal die Zeilen, die ich die Funktionen aufrufe:
//In TypListe sind nachweislich 3 Typen mit den Namen( foo, bar und baz ) Typ *tmp = NULL; TypListe.gibTyp( 0, tmp ); //tmp zeigt auf das erste Element in TypListe::typen cout << tmp->getName() << endl; TypListe.gibTyp( "foo", tmp ); // tmp bleibt NULL cout << tmp->getName() << endl; //<- gibt Folglich einen Absturz...Wenn ich mir die Namen aller Typen in der Liste ausgeben lasse, sehe ich "foo", "bar" und "baz". Ungewöhnlich ist jetzt, dass ersteres Funktioniert und zweiteres *nicht*. Bei der zweiten Methode ist tmp immer NULL. Wieso?
Wenn ich die zweite Methode mit Doppelpointern mache geht es komischerweise. Kann mir das jemand erklären?
MfG. Ich
-
ChristophLu schrieb:
class TypListe { vector<Typ*> typen; //... int gibTyp( size_t id, Typ* t ) { if( id >= this->typen.size() ) return -1; if( this->typen[id] == NULL ) return -2; t = this->typen[id]; return 0; } int gibTyp( string name, Typ* t ) { size_t i_max = this->typen.size(); for( size_t i = 0; i < i_max; ++i ) { if( this->typen[i] == NULL ) continue; if( this->typen[i]->getName() == name ) { t = this->typen[i]; return 0; } } return -1; } }; //... //In TypListe sind nachweislich 3 Typen mit den Namen( foo, bar und baz ) Typ *tmp = NULL; TypListe.gibTyp( 0, tmp ); //tmp zeigt auf das erste Element in TypListe::typen cout << tmp->getName() << endl;Hier stimmt etwas nicht. Der Kommentar passt nicht zu dem, was weiter oben steht. Falls dies hier wirklich so funktioniert, wie Du sagst, müsste eine Referenz auf den Zeiger an die Funktion gegeben werden, also
int gibTyp( size_t id, Typ*& t ) // t ist eine Referenz auf tmp // statt int gibTyp( size_t id, Typ* t ) // t ist eine Kopie von tmpTypListe.gibTyp( "foo", tmp ); // tmp bleibt NULL cout << tmp->getName() << endl; //<- gibt Folglich einen Absturz...Diese Kommentare passen wieder zum Code oben. gibTyp verändert tmp nicht, sondern nur eine lokale Kopie des Zeigers namens
t.Übrigens, für meinen Geschmack sind das zuviele Sternchen. Auch dass die Funktion gibTyp nicht direkt den gewünschten Eintrag zurück liefert sondern nur eine Art Fehlercode ist eher untypisch und macht den Code fehleranfällig und schlecht lesbar.
-
Hallo ChristophLu.
Das mit den Zeigern ist wohl ein gern gemachter Fehler. Denn du möchtest ja, dass dein übergebener Zeiger nach dem Aufruf auf das richtige Element zeigt. Jedoch übergibst du nur eine Kopie des Zeigers an die Funktion, wodurch diese dann höchstens den Inhalt ändern kann, worauf der Zeiger zeigt. Ändern könntest du es zum Beispiel mit einer Referenz auf den Zeiger(Typ*& t) oder einen Zeiger auf einen Zeiger(Typ** t). Die erste Möglichkeit wäre wohl ein wenig einfacher und ich glaube auch schneller ... Allerdings bin ich mir bei der Geschwindigkeit nicht ganz sicher.
Was ich aber auch nicht so ganz verstehe ist, warum dein erster Aufruf funktioniert: "TypListe.gibTyp( 0, tmp )". Eigentlich sollte da der Zeiger tmp nicht verändert werden.Gruß, Mickeyman.
-
Hm ... klingt irgendwie logisch. Aber ersteres Funktioniert ja und das andere nicht, obwohl beide Methoden den zeiger auf die gleiche Art und Weise übergeben.
int func( Typ* t ) //... t = this->elemente[i]Aber das mit der Referenz werde ich einbauen.
Übrigens, für meinen Geschmack sind das zuviele Sternchen.
Meinst du damit, dass ich den Zeiger von Typ will?
Auch dass die Funktion gibTyp nicht direkt den gewünschten Eintrag zurück liefert sondern nur eine Art Fehlercode ist eher untypisch und macht den Code fehleranfällig und schlecht lesbar.
Es gibt den gewünschten Eintrag zurück. Ich brauche direkt das Objekt. Es wäre glaub ich nicht sinnvoll, für jede Eigenschaft von Typ eine Methode in TypListe zu machen. Natürlich könnte ich den Vektor auch public machen( jetzt ist er private ), aber das bringt wenig, da die Funktionen, die TypListe benutzen, meistens nicht wissen, welcher Typ in welchem Vektoreintrag ist und ich so bequem eine Methode zum Suchen hab...
Zweck des Ganzen:
Ich habe Typen, die gewisse Eigenschaften haben. Um die Typen zu verwalten, zu filtern und sonst irgendwie als Ganzes zu modofizieren, ist TypListe da.MfG. Ich
-
Du versuchst mit dem Rückgabewert irgend einen Fehler mitzuteilen. Das ist ein (in meinen Augen) unnötiger Nebeneffekt, der die meisten nicht interessieren wird. Die ganze Angelegenheit wird deutlich angenehmer, wenn deine Funktion einen Pointer auf das Element returned oder eben NULL falls der index zu groß ist oder das Element nicht exisitiert.
Diese Zeileif( this->typen[id] == NULL ) return -2;ist doch irgendwie auch mistig

Wenn es jemanden interessiert, was denn jetzt eigentlich los ist, kann er ja nachträglich danach fragen:Typ* getTyp( size_t id ) { if( id > max_id ) return NULL; return types[id]; } ErrorCode errorForQuery( size_t id ) { returnIrgendEWinenError(); } /// Benutzung Typ* typ = typologe.getTyp(666); if( !typ ) printError( typologe.errorForQuery(666) );Nebenbei:
Dass es funktioniert ist halt ein Effekt des "undefined behaviour", wahrscheinlich hast du Glück, weil oben auf dem Stack noch die richtige Adresse liegt, im zweiten Falle ist da noch ein "int" dazwischen gerutscht. Aber wenn es funktioniert ist es Zufall, und hat nix mit der Signatur oder sonstwas zu tun.
-
ChristophLu schrieb:
Hm ... klingt irgendwie logisch. Aber ersteres Funktioniert ja und das andere nicht, obwohl beide Methoden den zeiger auf die gleiche Art und Weise übergeben.
Ganz sicher? Hast Du Dich auch nicht vertippt beim Abtippen? Die Funktionen sind bei dir ja auch
private. Sieht für mich nach fehlerhaft abgetippt aus.
-
krümelkacker schrieb:
ChristophLu schrieb:
Hm ... klingt irgendwie logisch. Aber ersteres Funktioniert ja und das andere nicht, obwohl beide Methoden den zeiger auf die gleiche Art und Weise übergeben.
Ganz sicher? Hast Du Dich auch nicht vertippt beim Abtippen? Die Funktionen sind bei dir ja auch
private. Sieht für mich nach fehlerhaft abgetippt aus.Was ich auch komisch finde, ist, dass im Titel etwas von Doppelzeigern steht, ich aber nirgens im Code Zeiger auf Zeiger sehe.
-
Ganz sicher? Hast Du Dich auch nicht vertippt beim Abtippen? Die Funktionen sind bei dir ja auch private. Sieht für mich nach fehlerhaft abgetippt aus.
Das liegt daran, dass ich zu faul war, erst noch mit private und public zu hantieren...
Was ich auch komisch finde, ist, dass im Titel etwas von Doppelzeigern steht, ich aber nirgens im Code Zeiger auf Zeiger sehe.
Na dann lies noch mal den ersten Post ... da stehts.
Das mit den Rückgabewerten liegt daran, dass es noch mehr Fehler geben kann. Aber je nach Fehler muss der User anders Reagieren, weswegen ich das mit den Rückgabewerten eben so gewählt habe.
Ach ja ... ich habs jetzt mit den Referenzen auf nen Zeiger gemacht ... also so:
int gibTyp( string name, Typ *&t );Problem ist somit gelöst.
MfG. Ich