operatoren [] =



  • hi,
    ich beschäftige mich gerade damit operatoren in meine klasse hinzuzufügen.
    dabei ist mir das zusammenspiel von operator Array [] und = nicht ganz klar.

    wenn ich einen zeichenfolgenpuffer habe

    char *m_pszString = new char [5];
    

    und m_pszString nun werte mittels den beiden operatoren [] = hinzufügen möchte, wie muss dann die funktion aussehen damit beide zusammen spielen.

    ich hab jetzt schon std. auf code project und msdn umgesehen und ein wenig in erfahrung gebracht. aber nichts brauchbares für mein problem gefunden.

    bisher mach ich es so...

    char& StringCtrl::operator [] (int iIndex)// Linksseitiger operator
    {
    	if(iIndex >= 0 || iIndex < GetSize())
    		return m_pszString[iIndex];
    	else
    		return m_pszString[GetSize()];
    }
    char StringCtrl::operator [] (int iIndex)const//Rechtsseitiger operator
    {
    	if(iIndex >= 0 || iIndex < GetSize())
    		return m_pszString[iIndex];
    	else
    		return m_pszString[GetSize()];
    }
    

    wenn ich dann versuche die Klasse wie folgt zu belegen

    StringCtrl sc;
    sc[0] = _T('A');
    sc[1] = _T('B');
    sc[2] = _T('C');
    sc[3] = _T('D');
    sc[4] = _T('E');
    sc[5] = _T('\0');
    

    motzt der compiler das er den operator = vermisst. und hier liegt jetzt mein problem. die beiden in einklang zu bringen. ich habe absolut keine idee wie die funktion für = aussehen muss, damit sie mit der funktion [] zusammenspielt.

    die funktion = unabhängig von funktion [] ist kein problem und funktioniert auch.
    bin für jede hilfe dankbar.
    ...



  • Hast du dein Programm mit Unicode-Settings compiliert? Wenn ja, verbirgt sich hinter _T('A') kein normaler char, sondern ein wchar_t. Wenn das das Problem ist, kannst du es lösen, indem du statt char TCHAR verwendest.

    Aber ansonsten hast du noch einige inhaltliche Probleme mit diesem Code - ich weiß zwar nicht, welchen Wert GetSize() zurückliefert, aber höchstwahrscheinlich liegt das Element m_pszString[GetSize()] außerhalb des von dir reservierten Speicherbereichs.



  • Hast du dein Programm mit Unicode-Settings compiliert?

    nein mit multi-byte

    ...ich weiß zwar nicht, welchen Wert GetSize() zurückliefert...

    ist ne selbst geschriebene funktion und gibt die größe von m_pszString + null terminierung zurück.
    im fall des linksseitigen operators sicherlich verkehrt, denn die null terminierung wollte ich nicht ankratzen:).

    aber wie spielen jetzt diese beiden operatoren [] = zusammen?



  • Dann solltest du eventuell die komplette Fehlermeldung angeben und nicht nur ein Schlagwort daraus. (normalerweise steht dort auch genau drin, welcher Operator erwartet wurde)

    Zu deiner Frage: Der Compiler zerlegt einen Ausdruck sc[index] = irgendwas; in zwei Funktionsaufrufe. Zuerst wird der operator[] deines Strings ausgeführt (einer der beiden, die du definiert hast*) und liefert eine Referenz auf eins der Elemente des dynamisch angelegten Speicherbereiches zurück. Danach wird der operator= dieser Referenz aufgerufen, um den Inhalt von irgendwas in das Element zu schreiben.

    Bei deiner Konstruktion ist der Operator sehr unsicher, besonders wenn GetSize() tatsächlich nach dem Null-Terminator sucht, um die String-Größe zu ermitteln, ein einfaches sc[10000]='a'; überschreibt dieses Ende-Zeichen und schon "wächst" der String in Bereiche, die ihn gar nichts angehen.
    (wenn du Glück hast, bekommst du beim nächsten Zugriff eine Schutzverletzung, wenn du Pech hast, erlaubt dir die CPU tatsächlich, dorthin zu schreiben).

    PS: Hat es eigentlich einen tieferen Sinn, daß du das Rad neu erfindest, anstatt mit bewährten Lösungen wie std::string zu arbeiten?



  • rein aus verständnisszwecken und spaß an der freude, versuch ich grad die CString Klasse nachzubauen. ich will bestimmt nicht das rad neu erfinden ;).

    die fehlermeldung (wie gesagt er vermist etwas)

    6>CLineCtrld.lib(CLineCtrl.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: class StringCtrl const & __thiscall StringCtrl::operator=(char)" (??4StringCtrl@@QAEABV0@D@Z)" in Funktion ""public: int __thiscall CLineCtrl::TrimRight(void)" (?TrimRight@CLineCtrl@@QAEHXZ)".

    in welcher reihenfolge mein pc den code interpretiert, weis ich. mir geht es ja um das zusammenspiel beider funktionen. deine erklärung

    Zu deiner Frage: Der Compiler zerlegt einen Ausdruck sc[index] = irgendwas; in zwei Funktionsaufrufe. Zuerst wird der operator[] deines Strings ausgeführt (einer der beiden, die du definiert hast*) und liefert eine Referenz auf eins der Elemente des dynamisch angelegten Speicherbereiches zurück. Danach wird der operator= dieser Referenz aufgerufen, um den Inhalt von irgendwas in das Element zu schreiben.

    hat mich jetzt weitergebracht imo funzt es. danke dafür... 👍
    für die = operation geh ich nun so vor.

    const StringCtrl& StringCtrl::operator = (char sz)
    {	*m_pszString = sz;
    
    	return *this;
    }
    

    es funktioniert jetzt zwar, allerdings frage ich mich ob die schreibweise so

    *m_pszString = sz;
    

    korreckt ist? 😮 oder geh ich da geradewegs durch sämtliche hintertüren?



  • .operator. schrieb:

    rein aus verständnisszwecken und spaß an der freude, versuch ich grad die CString Klasse nachzubauen. ich will bestimmt nicht das rad neu erfinden ;).

    die fehlermeldung (wie gesagt er vermist etwas)

    6>CLineCtrld.lib(CLineCtrl.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: class StringCtrl const & __thiscall StringCtrl::operator=(char)" (??4StringCtrl@@QAEABV0@D@Z)" in Funktion ""public: int __thiscall CLineCtrl::TrimRight(void)" (?TrimRight@CLineCtrl@@QAEHXZ)".

    Irgendwie habe ichn icht das Gefühl, daß sich diese Meldung auf deinen Code von oben bezieht - du hast irgendwo noch eine Zuweiseung der Art sz=_T('X'); in deinem Code (genauer in der Methode CLineCtrl::TrimRight()), die der Linker nicht aulösen konnte. Für den Code-Schnipsel, den du dort oben gepostet hast, benötigst du nur eine ZUweisung von char auf char - und die erzeugt der Compiler automatisch, ohne da- du dich darum kümmern mußt.

    Was deine Implementierung des Operators angeht - die dürfte im Gesamtkontext nicht wirklich das machen, was du erwartest:

    StringCtrl str = "Hallo";
    str = 'X';//hier wird dein operator= greifen
    // -> in str steht jetzt "Xallo"
    

    Bei den Zuweisungs-Operatoren und Konstruktoren deiner Klasse mußt du immer dafür sorgen, daß (a) genug Platz für die Eingabe inklusive '\0' ist, (b) am Ende der Daten das Abschlußzeichen angehängt* ist und (c) jeder String seine eigene Kopie der Daten hält (ja, es gibt auch Ansätze, die mit Referenzzählung und Copy-on-Write arbeiten, aber die dürften komplizierter sein). Und natürlich mußt du auch allen Speicher wieder freigeben, den du angefordert hast.

    Der Index-Operator von oben ist in diesem Zusammenhang etwas bedenklich - du überprüfst erst, ob der übergebene Index im "erlaubten" Bereich liegt und übergibst im Fehlerfall eine Referenz auf etwas zurück, was nicht im erlaubten Bereich liegt. Wenn deine Längenberechnung auf der Endemarke basiert, zerlegt dir der Anwender die Daten, wenn nicht, gehört dir das Element m_pszString[GetSize()] vermutlich gar nicht und eine Zuweisung dorthin zerlegt jemand anderem die Daten.

    *Eine Alternative besteht noch darin, die Länge in einer eigenen Membervariablen zu speichern, dann brauchst du kein Endezeichen, mußt aber bei jeder Operation die Größe aktualisieren.



  • wie schon gesagt...

    im fall des linksseitigen operators sicherlich verkehrt, denn die null terminierung wollte ich nicht ankratzen:).

    was die fehlermeldung genau heist, weis ich auch. du wolltest sie sehen, deshalb habe ich sie gepostet.

    der zeichenfolgenpuffer ist 46 karaktere groß, also groß genug. ich spiel gerade mit den ersten 5 karakteren. ich schiese also nicht übers ziel hinaus. auch sollte die größen überschreitung imo nicht der diskusionspunkt sein. denn die operatoren sollen erst mal funktionieren, dann kümmer ich mich darum was passiert wenn der index größer ist als der zeichenfolgenpuffer. imo geb ich ja alles mit der hand ein. ich bewege mich also im sicheren speicherbereich.

    auch habe ich gerade festgestellt, das es mir in der funktion

    const StringCtrl& StringCtrl::operator = (char sz)
    {    *m_pszString = sz;
    
        return *this;
    }
    

    mit

    StringCtrl sc;
    sc[0] = _T('A');
    

    nur die erste position in m_pszString belegt. sobald ich die Positionsnr erhöhe

    sc[1] = _T('B');
    

    kommt ne Assertdebugmeldung bezogen auf diese zeile.

    *m_pszString = sz;
    

    sz hält dort den richtigen wert und m_pszString ist ein schlechter Pointer.



  • Zeig doch mal etwas mehr Code, damit andere den Fehler nachvollziehen können. (außerdem wäre es mal eine gute Idee, sich das Problem im Debugger anzusehen)



  • statt

    *m_pszString = sz;
    

    lieber so:

    m_pszString[0] = sz;
    

Anmelden zum Antworten