Wie erzeuge ich Operatoren unter C++?

Ich habe ein kleines Problem. Mein Operator zerstoert mir offenbar die Instanz, so dass wenn ich spaeter wieder darauf zugreife (nach einer erneuten Instanzierung) malloc SegFaults erzeugt.

 friend inline bool operator==( EPSString es, char \*cs );

private:

 char \*storeValue;
};

inline bool operator==( EPSString es, char \*cs ) {
 EPSString \*temp = new EPSString(es.getCString());
 int n = temp-\>compare(cs);
 delete(temp);
 if (n == 0)
 return true;
 else
 return false;
}

Die Funktion getCString() erzeugt eine char * Instanz des Objekts, und compare vergleicht die den uebergebenen String mit storeValue mit Hilfe von memcmp, bzw. strcmp.

Ausserdem: Generelle Frage, mache ich alles richtig? Ich habe das ganze von QString aus QT 2.1.0 kopiert.
Benutzen tue ich gcc mit glibc 2.1.0. Eine Loesung sollte moeglichst AnsiC++ kompatibel bleiben, und fremde Bibliotheken (ausser solchen die bei Linux standardmaessig dabei sind) vermeiden.

Muß zwar nichts mit deinem Problem zu tun haben, aber warum schreibst du statt:

EPSString *temp = new EPSString(es.getCString());
int n = temp->compare(cs);
delete(temp);

nicht:

int n = es.compare(cs);

?

Eventuell tut auch sowohl das getCString als auch der Konstruktor vom EPSString referenzieren und nicht kopieren und du machst dir durchs delete dann im es was kaputt.

Weiß auch nicht ob inline in diesem Fall so gut ist, dürfte ihm zwar nicht weh tun, bringt aber auch nichts.

Grüße, Robert

Hi Roland :wink:

Hmm, das geht bei dir ja ziemlich wild durcheinander. Um zu sagen, wo der Fehler ist, bräuchte ich noch die Deklaration von EPSString.

Erstmal solltest du aber die Funktion vernünftig formulieren:

bool operator == (EPSString es, char \*cs) {
 return 0==strcmp(es.getCString,cs); }

Vermutlich ist der Fehler dann schon weg :wink:

cu Stefan.

Hallo Roland !

Ich glaube mit ziemlicher Sicherheit Deinen Fehler zu sehen.
Probiers mal so :

friend inline bool operator==( EPSString & es, char \*cs );
private:
 char \*storeValue;
};

bool operator == (EPSString & es, char \*cs)
{
 return 0==strcmp(es.getCString,cs);
}

Nun die etwas laengliche Erklaerung:

Du uebergibst Deiner Funktion operator == ein EPSString Objekt, ohne ihr gesagt zu haben wie ein solches Objekt kopiert wird. Daraufhin kopiert der Compiler einfach alle Datenmember (auch den char*) auf das neue Objekt es.
z.B.

EPSSTring x(„Hallo“);
char test[]=„Hallo“;
if (x==test)

Du hast ausserhalb Deiner Funktion ein Objekt x welches einen char * beinhaltet fuer den Du im Konstruktor Speicher angelegt hast. Beim Aufruf von operator == wird das Objekt x wegen des fehlenden Kopierkonstruktors (EPSString( EPString &amp:wink:) einfach kopiert. Kopieren heisst dann den char * einfach zu kopieren. x und es haben also identische char *. Wenn der Scope der Funktion operator == verlassen wird, wird folgerichtig der Destruktor von es aufgerufen. Dieser gibt den Speicher, auf welchen char * zeigt einfach frei. Damit hast Du dann gleich den char * in x zerstoert (weil ja identisch), so dass es beim naechsten Zugriff auf x zu Fehlern kommt.

Nun die Loesung:
Wenn Dein Objekt Zeiger verwaltet, die auf allocierten Speicher zeigen bekommst Du bei jedem Funktionsaufruf bei welchen Du ein Objekt uebergibst das selbe Problem. Um dies zu loesen musst Du entweder

A: nur eine Referenz auf Dein Objekt uebergeben also wie oben gezeigt EPSString & . Der Destruktor wird dann nicht aufgerufen, da x und es dann zwei Namen fuer das selbe Objekt sind. Dann hast Du aber das Problem, dass Dein uebergebenes Objekt in der Funktion veraendert werden koennte. Um ein Aendern zu verbieten, ist die sauberste und vor allem schnellste Loesung das Objekt als const zu markieren. Die Mustergueltige Deklaration fuer == waere dann.

friend inline bool operator==(const EPSString & es, char \*cs );

B: Du sagst dem Compiler, dass er einen EPSString nicht einfach durch das duplizieren aller Membervariablen kopieren darf indem Du eine Kopierkonstructor erzeugts in welchem Du neuen Speicher anlegst und den ganzen String auf diesen kopierst (langsam und speicherfressend).
Die Deklaration fuer den Kopierkonstruktor waere dann:

public:
EPSString(const EPSString & es);

Dann brauchst Du die Objekte nicht mehr als Referenz zu uebergeben.
Hoffentlich habe ich mich halbwegs verstaendlich ausgedrueckt.

Anmerkung:
Wieso deklarierst Du den operator als friend und nicht als Memberfunktion ?
Fuer den Vergleich EPSString==char * kannst Du den Operator als Memberfunktion deklarieren. Die Funktion wird dann fuer das links vom operator stehende Objekt aufgerufen.
Fuer den Vergleich (char*)==EPSString gehts allerdings nur als friend.
Die Deklaration fuer die beiden Vergleiche waeren dann.

public:
//EPSString == (char \*) als Memberfunktion
inline bool operator==(char \*cs );
//(char \*)==EPSString geht nur als friend
friend inline bool operator==(char \*cs, const EPSString &amp:wink:;

Tschuess !

Andreas

Danksagung
Danke, fuer alle Loesungen, habe es mittlerweile geschafft, dank eurer Hilfe.

Hi Roland !

Das mit der Referenz-Übergabe könnte der Fehler sein. Um wirklich sicher zu gehen, hätte ich nur gerne vorher die Deklaration von EPSString gesehen. Und um zukünftige Fehler dieser Art dann zu vermeiden, hätte ich auf jeden Fall noch einen vernünftigen Copy-Constructor definiert! Was meinst du?

Wie dem auch sein, deine Lösung sollte auf jeden Fall funktionieren :wink:))

cu Stefan.

Hallo Stefan !

Das mit der Referenz-Übergabe könnte der
Fehler sein. Um wirklich sicher zu gehen,
hätte ich nur gerne vorher die
Deklaration von EPSString gesehen.

Mein Tipp hat sich auf einige Vermutungen hinsichtlich des Aufbaus von EPSString gestuetzt (Speicherreservierung im Konstruktor und Freigabe im Destruktor). Ich denke allerdings, dass ich damit nicht so falsch lag.

Und um
zukünftige Fehler dieser Art dann zu
vermeiden, hätte ich auf jeden Fall noch
einen vernünftigen Copy-Constructor
definiert! Was meinst du?

Copy - Contruktor ist immer zu gebrauchen, da man dann mit Sicherheit ein einfaches Kopieren der Membervariablen ausschliesst (auch an allen anderen Stellen ausser operator ==). Trotzdem wuerde ich an alle Funktionen und Operatoren nur const Referenz - Objekte uebergeben, weil das viel schneller und speicherschonender ist. Der String koennte ja ganz schoen lang sein und sollte deshalb nicht fuer jeden Funktionsaufruf kopiert werden.

Wie dem auch sein, deine Lösung sollte
auf jeden Fall funktionieren :wink:))

Hoffe ich auch !

cu Stefan.

Viele Gruesse !

Andreas