Index-Operator überladen?



  • Das ist der Quellcode

    template <typename T> class Liste{
    protected:
    T* Inhalt;
    unsigned Index;
    public:
    
    T& operator[](unsigned idx);
    

    Jetzt habe ich gehört, dass der Compiler aus solchen Indexausdrücken wie:
    [cpp]
    Liste <int> array;
    array[1] = 2;
    [/cpp]

    seinerseits intern in eine Zeigeraddition verwandelt, nach diesem Muster:

    *(array+1)=2;
    

    Überladen habe ich aber nur den '[] Index-Operator', nicht aber den '+ Operator für Zeigertypen'. Müsste ich also auch den + Operator noch zusätzlich überladen, damit der [] Index-Operator funktioniert?



  • Nein, mußt du nicht.



  • hallo

    in einem programm möchte ich gerne den Index Operator [] überladen.
    Wenn ich das in einem ganz einfachen beispiel versuche

    astring operator [](int i) ;

    astring operator [](int i)
    {
    return 0;
    }

    bekomm ich immer folgende meldung.

    error C2801: "operator []" muss ein nicht statischer Member sein.

    was soll mir dieser fehler sagen?



  • physikus schrieb:

    was soll mir dieser fehler sagen?

    Diese Fehlermeldung soll dir sagen dass "operator []" ein nicht statischer Member sein muss.



  • merci...
    und was bedeutet das?
    warum ist das denn ein statischer member, und wie mache ich daraus einen nicht statischen?



  • du kannst den [] Operator nur als nicht statisches klassenmember überladen, aber nicht global.



  • und wie sieht sowas dann aus???



  • struct A{
        int *data;
    
        int & operator[](const unsigned &index){ return data[index]; } // OK, nicht-statische memberfunktion
    
        static int & operator[](const unsigned &index){ return data[index]; } // falsch, statische memberfunktion
    };
    
    int & operator[](const A &a, const unsigned &index){ return a.data[index]; } // falsch, globale funktion
    


  • hmm... ich habs jetz auch selbst hin bekommen:
    sieht so aus:

    char operator [](int i); 
    
    char astring::operator [](int i)                               // Überladen []
    { 
    astring::buchstabenliste *b   =  astring::Getstring();
    char x;
    
    	for (int j=0; j<=i;j++)
    		{
    		x=(*b).buchstabe;
    		b=(*b).next;
    		};
    return x;
    }
    


  • hmm ... zeig mal deine ganze Stringklasse ... scheinst ja wieder am rumfrickeln sein ^^

    char astring::operator [](int i)
    {
        Item* pElement   = m_Begin;
        for (unsigned int pos = 0; (pos <= i && pElement); ++pos; pElement = pElement->pNext);
        return pElement->letter;
    }
    

    ...



  • so, hier die string (astring) klasse

    #pragma once
    class astring 
    { 
    struct buchstabenliste {
    		char buchstabe;
    		buchstabenliste *next;};
    
    public:
    astring ();														//Konstruktor
    astring (const char* text );									//Konstruktor
    ~astring ();
    int lenght();													// gibt die Länge aus
    buchstabenliste *beginn;
    astring::buchstabenliste * Getstring ();
    astring operator+(astring lhs);
    
    friend ostream& operator<<(ostream&,const astring& str);		//überladen <<
    char operator [](int i);
    
    private: 
    int size;
    
    };
    

    das mit dem [] funktioniert eigentlich super, das einzigste was noch nicht funktioniert ist das überladen des + operators.

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-184268.html

    astring astring::operator +(astring lhs)                    
    {  
    	astring::buchstabenliste *b   =  astring::Getstring();
    	astring::buchstabenliste *a   =  lhs.beginn;
    
    	char x;
    	int i=astring::lenght();
    	for (int j=0; j<=i;j++)
    		{
    		x=(*b).buchstabe;
    
    		b=(*b).next;
    		};
    
    	//cout <<(*a).next->buchstabe; //nur zum testen
    	//cout <<(*b).next->buchstabe; //nur zum testen
    
    	return  lhs;
    }
    

    Da hab ich halt noch das problem das ich nicht weiß wie ich den "zeiger auf die verkettete liste" als typ "astring" dereferenzieren soll?

    dann bin ich fertig, im wahrsten sinne des wortes sogar fix und fertig



  • hmm mal ein paar veränderungen 🙂

    #if !defined (STRING_H__INCLUDED)
    #define STRING_H__INCLUDED
    
    #if (_MSC_VER > 1000)
    #pragma once
    #endif // (_MSC_VER > 1000)
    
    namespace str
    {
    	template <typename T>
    	class basic_string
    	{
    	public:
    		basic_string() : m_begin(NULL), m_size(0) {}
    		basic_string(const T* str) : m_size(0)
    		{
    			m_begin = new Item(NULL, str[m_size]);
    			++m_size;
    			Item* ptr = m_begin;
    			for (; str[m_size]; ++m_size)
    			{
    				ptr->next = new Item(NULL, str[m_size]);
    				ptr = ptr->next;
    			}
    		}
    
    		~basic_string()
    		{
    			for (Item* cur = m_begin; cur;)
    			{
    				Item * tmp = cur->next;
    				delete [] cur;
    				cur = tmp;
    			}
    		}
    
    		basic_string& operator+=(const basic_string& str)
    		{
    			Item* end = m_begin;
    			while (end->next)
    				end = end->next;
    			for (Item* cpy = str.m_begin; cpy; cpy = cpy->next)
    			{
    				end->next = new Item(cpy);
    				end = end->next;
    				++m_size;
    			}
    			return *this;
    		}
    
    		//const T* operator()  { /* hier einen const T* (also const char*) zurückgeben. Dann brauchst du keinen Streamoperator!*/ }
    		T operator [](std::size_t i)
    		{
    			Item* cur   = m_begin;
    			for (std::size_t pos = 0; (pos <= i && cur); ++pos, cur = cur->next);
    				return cur->ch;
    		}
    
    	public:
    		std::size_t		size() const	{ return m_size;	}
    		std::size_t		length() const	{ std::size_t len = 0; for (Item* ptr = m_begin; ptr && ptr->ch; ++len, ptr = ptr->next); return len;	}
    
    	private:
    		struct Item 
    		{
    			T ch;
    			Item* next;
    			Item() : ch(0), next(NULL) {}
    			Item(Item* next, T ch) : ch(ch), next(next) {}
    			Item(const Item& it) : ch(it.ch), next(it.next) {}
    		} m_begin;
    		std::size_t m_size;
    
    	};
    
    	typedef basic_string<char> cstring;
    	typedef basic_string<unsigned char> ucstring;
    	typedef basic_string<wchar_t> wstring;
    };
    
    #endif // STRING_H__INCLUDED
    

    =>

    #include <iostream>
    #include "string.h"
    
    int main()
    {
        str::cstring tmp("Das ist schön!");
        std::cout << tmp << std::endl;
    }
    

    ...



  • Hallo
    Danke erstmal für deine mühe, aber leider hab ich noch einige verständnisprobleme. Das ganze ist für mich als anfänger wohl etwas zu professionell.

    basic_string() : m_begin(NULL), m_size(0) {}
    

    was bedeutet hier der doppelpunkt? und die parameter dahinter?

    wie funktioniert das genau mit dem template?

    basic_string() : m_begin(NULL), m_size(0) {}
    

    muss m_begin nicht irgendwie ein zeiger sein?

    Bei deiner struct versteh ich auch nur die hälfte, und den ostrem muss ich aufgrund der geforderten Aufgabenstellung überladen.



  • so... hab jetzt mal ne nacht drüber geschlafen, und jetzt funktionierts

    astring::buchstabenliste *b   =  astring::Getstring();
    	astring::buchstabenliste *a   =  lhs.beginn;
    
    	astring str="                                              ";
    	buchstabenliste* temp =str.beginn;
    
    	while ( (*b).buchstabe)
    		{
    		(*temp).buchstabe=(*b).buchstabe;
    		temp=temp->next;
    		b=b->next;
    		};
    
    	while ( (*a).buchstabe)
    		{
    		(*temp).buchstabe=(*a).buchstabe;
    		temp=temp->next;
    		a=a->next;
    		};
    
    	return  str;
    

    ist zwar nicht so ganz ideal die lösung, aber funktion ist alles 😉
    jetzt änder ich das noch mit dem neuen astring das er die elemente selber in der schleife erzeugt und dann bin ich endlich fertig.



  • physikus schrieb:

    basic_string() : m_begin(NULL), m_size(0) {}
    

    was bedeutet hier der doppelpunkt? und die parameter dahinter?

    Hinter dem Doppelpunkt befindet sich die Initialisierliste des Konstruktors. m_begin wird auf NULL gesetzt, m_size ebenfalls. (Unter dem Begriff Initialisierliste solltest du auch in irgendeinem Tutorial finden, warum man sie manchmal braucht)

    physikus schrieb:

    wie funktioniert das genau mit dem template?

    Templates schnell umrissen: Du schreibst danach basic_string<meintyp> und er ersetzt ueberall wo du T stehen hast das T durch meintyp. In diesem Fall nutzt DEvil das um fuer normale chars, vorzeichenlose chars (unsigned char) und wide characters (w_chart) die Klasse nutzen zu koennen, wie du an den typedefs hinter der Klasse sehen kannst.

    [quote="physikus"]
    Bei deiner struct versteh ich auch nur die hälfte[quote]

    struct Item 
            {
                T ch;  //Das Zeichen, das wir abspeichern (du bastelst hier ja ne Zeichenkette
                Item* next;  //wo steht das naechste Zeichen (muss man ja irgendwie wiederfinden)
                Item() : ch(0), next(NULL) {}  //Default Konstruktor
                Item(Item* next, T ch) : ch(ch), next(next) {}  //Konstruktor, speichere das Zeichen ch und das naechste Zeichen nach dem hier steht bei next
                Item(const Item& it) : ch(it.ch), next(it.next) {} //Copy-Konstruktor, wenn wir ein Item haben und es kopieren wollen.
            } m_begin;
    

    Ich hoffe ich habe jetzt nichts verwechselt, wenn doch bitte korrigieren.


Anmelden zum Antworten