+operator ueberladen
-
Wäre als Rückgabewert für den operator nicht const String angebracht?
Verkehrt wäre es sicher nicht. Sutter argumentiert in "Exceptional C++" dafür. Lakos in "Large Scale C++ Software Design" dagegen.
Mir ist es wurscht und deshalb bin ich da leider nie wirklich konsequent.
-
wie jetzt ?
muss ich die funktion ausserhalb der klasse definieren ?
// h-file class TxlString; char* operator+(char &t_char, TxlString &t_string); class TxlString { ... }; // cpp-file char* operator+(char &t_char, TxlString t_string) { unsigned int t_size = sizeof(&t_char) + t_string.Size(); char t_str = new char[t_size]; memcpy(t_str, &t_char, t_size - t_string.Size()); memcpy(t_str + (t_size - t_string.Size()), t_string.string,t_string.Size()); return t_str; }
da gibt er mir aber immer fehler aus. oder habt ihr das anders gemeint ??
Meep Meep
-
beim testen krieg ich dann "ungueltige Strukturoperation" wenn ich das testen will.
TxlString eingabe = "test";
TxlString ausgabe = "test" + eingabe;Meep Meep
-
// h-file class TxlString; TxlString operator+(const char *t_char, const TxlString &t_string); class TxlString { ... }; // cpp-file TxlString operator+(const char *t_char, const TxlString &t_string) { TxlString tmp(t_char); tmp += t_string; //benutze einfach den += operator return tmp; }
den += operator natürlich in der klasse definieren.
-
den operator+= hab ich ja drinnen. der funkt ja auch.
das problem liegt beim operator+ich will folgendes machen koennen:
TxlString = char + TxlString;und in dem fall nutzt mir der operator+= nicht wirklich was
Meep Meep
-
@MeepMeep: Ich hätt da nen Vorschlag: Lies doch mal die Beiträge von Hume und davie.
@Hume:
Kannst Du kurz die Gründe, die Lakos dagegen bringt nennen? Den hab ich nämlich (noch) nicht. Meyers sagt ja: "do as the ints do" und das klingt für mich eigentlich sinnvoll.
-
hab das jetzt zum teil geschafft. keine fehlermeldung mehr. mein fehler lag im funktionsrumpf. aber er schient mir den char-string nicht reinzukopieren.
// h-file TxlString operator+(const char &t_char,const TxlString &t_string); class TxlString { ... friend TxlString operator+(char *t_char,const TxlString &t_string); ... }; // cpp-file TxlString operator+(char *t_char,const TxlString &t_string) { unsigned int t_size = strlen(t_char); unsigned int t_size_all = t_size + t_string.size; TxlString t_str; t_str.string = new char[t_size_all]; memcpy(t_str.string, t_char, t_size); // (1) memcpy((t_char + t_size), t_string.string, t_string.size); return t_str; }
aber irgendwie funkt das noch net richtig.
TxlString test = "Meep Meep"; TxlString ausgabe = "test:" + test;
bei der ausgabe kommt dann nur "Meep Meep". ohne "test:".
bei (1) wird der char jedoch reinkopiert.irgendwie steh ich jetzt voll auf dem schlauch
Meep Meep
-
Kopier Dir doch einfach mal den operator+ von davie. Der müßte eigentlich funktionieren.
MfG Jester
-
soooo
also, ich hab jetzt den code von davie kopiert.
aber des funkt auch nicht. da ziegt er mir in der messagebox nur ein kaestchen an. also irgendwas.habs mal vorsorglich getestet, um fehler in anderen operatoren auszuschliessen.
TxlString s1 = "test: "; TxlString s2 = "Meep Meep"; s1 += s2; char s3[] = ":noch ein test:"; s1 = s3 + s2; ShowMessage(s1.string); (1) TxlString s1 = "test:"; ShowMessage(s1.string); (2) TxlString s2 = "Meep Meep"; s1 += s2; ShowMessage(s1.string); (3) s1 = s2 + ":noch ein test:"; ShowMessage(s1.string); (4)
(1) funkt wieder nicht. (2), (3) und (4) funken wunderpraechtig.
bei (1) hab ich bei der ausgabe so das gefuehl als wenn der pointer irgendwohin zeigt, nur net dorthin wo er sollte.
Meep Meep
-
hab jetzt mal in der operator+ funktion von davie mir den string vor dem return anzeigen lassen. da stimmt noch alles.
aber draussen funktionierst dann nicht mehr. da scheinen dann die daten nicht mehr zu existieren.Meep Meep
-
hab jetzt mal in der globalen operator+ funktion den wert von t_char angeguckt.
char* operator+(char *t_char,const TxlString &t_string) { TxlString tmp(t_char); tmp += t_string; //benutze einfach den += operator ShowMessage("debug: " + AnsiString(t_char)); // (2) return tmp.string; } TxlString s1 = "s1, "; TxlString s2 = "s2, "; s1 = s1 + "test: " + s2; // (1) ShowMessage(s1.string); // (3)
beim aufruf in zeile (1) wird doch die operator+ funktion aufgerufen.bei (2) wird mir jedoch der string s1 + "test: " angezeigt. also "debug: s1, test:".
wieso steht da schon der wert von s1 drinnen ? wird (1) nicht von rechts nach links aufgeloest ??? und bei (3) kommt sowieso nur bloedsinnjemand ne idee ?
Meep Meep
-
so, darf ich mal kommentieren;
//erster parameter: char*. sollte ein const char * sein char* operator+(char *t_char,const TxlString &t_string) { TxlString tmp(t_char); //du erzeugste einen lokalen TxlString tmp += t_string; ShowMessage("debug: " + AnsiString(t_char)); return tmp.string; //und du gibst desen C-String zurück. doch leider wird //tmp nach Beenden der funktion vernichtet. der c-string wird ungültig (ich nehme //an du löscht ihn im destruktor von TxlString) } //rückgabe wert ist char*. Sollte wohl TxlString (oder const TxlString) sein. TxlString s1 = "s1, "; TxlString s2 = "s2, "; s1 = s1 + "test: " + s2; //das wird jetzt wohl aufgelöst zu s1.operator=(operator+(s1,operator+("test: ", s2));
lass den operator TxlString zurückgeben, und ändere char nach const char*
mache analog zu diesem operator einen operator+ für zwei TxlString und einen TxlString und ein const char*.
-
langsam glaub ich, das ich dafuer zu bloed bin
// h-datei TxlString operator+(const char *t_char,const TxlString &t_string); class TxlString { ... friend TxlString operator+(const char *t_char,const TxlString &t_string); ... }; // cpp-file TxlString operator+(const char *t_char,const TxlString &t_string) { TxlString t_str; unsigned int t_size = strlen(t_char); t_str.size = t_size + t_string.size; t_str.string = new char[t_str.size]; memcpy(t_str.string, t_char, t_size); memcpy(t_str.string + t_size, t_string.string, t_string.size); ShowMessage(t_str.string); // (1) return t_str; } // da teste ich TxlString s2 = "s2, "; s1 = "test: " + s2; ShowMessage(s1.string); (2)
bei (1) krieg ich noch das gewuenschte ergebnis, bei (2) nur noch muell
bin ich bloed oder was hab ich anders gemacht, als du es mit sagtest ?
string wird im destructor von TxlString geloescht.folgendes hab ich im inet gefunden:
class tBruch { ... friend tBruch operator+(long o1, const tBruch& o2); ... }; tBruch operator+(long o1, const tBruch& o2) { tBruch summe; summe.zaehler = o2.zaehler+o1*o2.nenner; summe.nenner = o2.nenner; return summe; }
da wird ja auch nur ein temporaeres objekt erzeugt und mittels return weitergegeben. was ist da anders als bei mir ?
Meep Meep
-
Jester schrieb:
@Hume:
Meyers sagt ja: "do as the ints do" und das klingt für mich eigentlich sinnvoll.Das ist auf jeden Fall richtig. Allerdings ist das hier etwas problematisch. Operatoren wie der op+ liefern für fundamentale Typen ein rvalue by value, und haben die Form:
T operator op(T, T)
Da der Rückgabewert ein rvalue ist, kann man weder die Adresse des Ergebnisses nehmen, noch es z.B. auf die linke Seite einer Zuweisung schreiben.
Auf dem gelieferten rvalue eines binären Operators eines udts kann man aber so oder so Memberfunktionen aufrufen. Im Falle eines const-Ergebnisses dann halt nur const-Memberfunktionen.
Der klare Vorteil eines const-Rückgabewerts ist aber natürlich, dass man ihn nicht auf der linken Seite einer Zuweisung gebrauchen kann.
Kannst Du kurz die Gründe, die Lakos dagegen bringt nennen?
Viel ist das nicht:
Results returned from a function by value are rvalues. In the case of fundamental types, declaring an rvalue const is redundant, confusing, and can interfere with template instantiation. [...]
An rvalue if a user-defined type (e.g. an object returned by value from a function) can be manipulated by non-const member functions; an object returned by value as const cannot[...]
Since the value returned is a copy anyway, exploiting the notion of a const versus a non-const rvalue is typically unnecessary.Letztlich kann man hier das Verhalten von ints nicht vollständig nachbilden, da ints nun mal keine Methoden besitzen.
Wenn ich daran denke, bevorzuge ich Sutters Sichtweise. Wie man allerdings gesehen hat, denke ich nicht immer dran
-
heisst das dann, das ich TxlString = char + TxlString ueberhaupt nicht verwenden kann ? oder wie war das zuverstehen ?
vorhin hatte ich in meiner normalen operator+ funktion nen fehler drinnen gehabt. scheinbar kann man gar kein temp. objekt zurueckgeben und damit weiterarbeiten. wie kann man sowas sont noch loesen ?
bei String , AnsiString funktioniert das doch auch.Meep Meep
-
Meep Meep schrieb:
heisst das dann, das ich TxlString = char + TxlString ueberhaupt nicht verwenden kann ? oder wie war das zuverstehen ?
Wie war das doch gleich mit links und rechts? Vielleicht hilft ein Bild:
[...............] = [...............] ^ ^ | | Hier ist links Hier ist rechts
wie kann man sowas sont noch loesen
Wie man dein Problem löst wurde hier bereits mehrfach gesagt. Vielleicht solltest du nochmal tief Luft holen, dann die Antworten nochmal langsam lesen und wenn dann das Verständnis einsetzt mit dem Programmieren beginnen.
Wenn es dann immer noch nicht klappt, poste dein *konkretes* Problem, also inklusive etwaiger Compilerfehler.PS: Es gibt keinen Grund den operator+ zu einem friend zu machen
PPS: Mein letzter Beitrag richtete sich an Jester. Du kannst ihn also getrost ignorieren.
-
hi HumeSikkins
wo links und rechts liegt, weiß ich schon seit geraumer zeit.
mein problem:
zuerst meine neugeschriebene klasse:
// h-datei class TxlStrings { private: // Methoden // Variablen unsigned int size; public: // Konstruktor und Destruktor TxlStrings(void); TxlStrings(char *t_char); ~TxlStrings(void); // Methoden unsigned int Size(void) { return size; } TxlStrings operator=(char *t_char); TxlStrings operator=(const TxlStrings &t_string); TxlStrings operator+(const TxlStrings &t_string); // Variablen char *string; }; // cpp-datei TxlStrings::TxlStrings(void) { size = 0; string = 0; } TxlStrings::~TxlStrings(void) { if(string) delete[] string; } TxlStrings::TxlStrings(char *t_char) { unsigned int size = strlen(t_char) + 1; string = new char[size]; memcpy(string, t_char, size); } TxlStrings TxlStrings::operator=(char *t_char) { unsigned int t_size = strlen(t_char) + 1; if(size < t_size) { if(string) delete[] string; size = t_size; string = new char[size]; memcpy(string, t_char, size); } else { size = t_size; memcpy(string, t_char, size); } return *this; } TxlStrings TxlStrings::operator=(const TxlStrings &t_string) { if(size < t_string.size) { if(string) delete[] string; size = t_string.size; string = new char[size]; memcpy(string, t_string.string, size); } else { size = t_string.size; memcpy(string, t_string.string, size); } return *this; } TxlStrings TxlStrings::operator+(const TxlStrings &t_string) { TxlStrings t_str ; t_str.string = new char[t_string.size + size - 1]; memcpy(t_str.string, string, size - 1); memcpy(t_str.string + size - 1, t_string.string, t_string.size); return t_str; }
der operator+ funktioniert jedoch nicht. er gibt mir scheinbar nix mehr zurueck.
TxlStrings a = "test1"; TxlStrings b = "test2"; TxlStrings c = a + b; ShowMessage(c.string); // (1)
da kommt bei (1) dann garnix. der operator+ uebergibt sozusagen der variablen c nix.
keine fehlermeldung oder sonstiges.
-
Oh man. Back to square one.
Waren wir zwischendurch nicht schon mal soweit, den Operator+ *nicht* als Member zu implementieren?Wo ist dein Copy-Ctor?
-
so hab jetzt den operator+ folgend global geschrieben:
TxlStrings operator+(const TxlStrings &l_string, const TxlStrings &r_string ) { TxlStrings t_str; ShowMessage(IntToStr(l_string.size + r_string.size - 1)); char *test = new char[l_string.size + r_string.size - 1]; t_str.size = l_string.size + r_string.size - 1; t_str.string = new char[l_string.size + r_string.size - 1]; memcpy(t_str.string, l_string.string, l_string.size - 1); memcpy(t_str.string + l_string.size - 1, r_string.string, r_string.size); return t_str; } // copy construktor TxlStrings::TxlStrings(TxlStrings &t_string) { size = t_string.size; string = new char[size]; memcpy(string, t_string.string, size); }
aendert aber nix an der tatsache, das er entweder nix oder nur wirres zeugs ausgibt. geschweige ich mach nen operator+ fuer (char*,TxlStrings).
Meep Meep
-
Nutze halt mal ein bisschen mehr die Konstruktoren und bereits fertige Operatoren.
inline const String operator+(const String &s1, const String &s2) { String tmp(s1); // Kopierkonstruktor tmp += s2; return tmp; } // Jetzt musst du natürlich noch += definieren ;). Oder willst du // für jeden Operator einen fetten Block Anweisungen mit memcpy // schreiben, bis irgendwann doch ein Fehler drin ist?
Bei MIR sieht das jetzt nachfolgend so aus:
void String::operator+= (const String &otherString) { (*this) += otherString.data; }
Und das ruft wiederum diese Operation auf:
void String::operator+= (TCHAR *otherString) { // Erforderliche Gesamtlänge bestimmen: const int length = (int)_tcslen(data) + (int)_tcslen(otherString) + 1; // In einem temporärem String zusammenfügen: TCHAR *temp = new TCHAR[length]; _tcscpy(temp, data); _tcscat(temp, otherString); // Den String in das L-Value Objekt übertragen: delete[] data; data = new TCHAR[length]; _tcscpy(data, temp); // Temprären String löschen: delete[] temp; }
Und das ist die einzige Stelle überhaupt, wo ich wirklich was arbeite. Alle anderen Operationen beziehen sich darauf.