Überladen des Inkrement-Operator



  • Ich habe mich jetzt mal mit dem Überladen von Operatoren auseindergesetzt, komme aber nicht wirklich zurecht. Hier mal die Klasse mit dem Versuch:

    class WEIRD
    {
        public:
            int i;
    
            template <class T>
            T& WEIRD::operator++ ()
            {
                return --T;
            }
    };
    

    Der Operator soll eben irgendeinen Typ dekrementieren. Wenn ich das aber mit i probier, wird i inkrementiert und nicht dekrementiert.



  • In deinem Fall weiss der Compiler nicht, dass er auf int arbeiten soll, die Operator wird lediglich auf WEIRD ausgeführt.



  • Du kannst keinen Operator für fremde Objekte auf die Weise überladen - und einen Typ zu dekrementieren macht auch herzlich wenig Sinn (erstaunlich, daß der Compiler das '--T;' überhaupt schluckt).

    PS: Was hast du eigentlich vor?



  • Du kannst keinen Typen Inkrementieren oder Dekrementieren.
    T ist ein Typ und keine Variable.
    Im Übrigen solltest du auch mal die Forensuche benutzen, so was ist hier schon lange vor dir beantwortet worden 😉



  • Warum du ein Template benutzt, weiß ich jetzt nicht...

    Es könnte so aussehen (ungetestet):

    class Foo
    {
    private:
        int value;
    
    public:
        Foo();
        Foo(int value);
    
        Foo& operator++();
    };
    
    // [...]
    
    Foo& Foo::operator++()
        {
            value++;
            return *this;
        }
    

    Das return *this (zur Erinnerung: this ist ein Zeiger und ein Referenz wird zurückgegeben) ist notwendig, damit ausdrücke wie

    Foo foo(12);
    Foo bar = foo++;
    

    möglich sind (die Zweite Zeile ruft den Kopierkonstruktor von Foo mit der (konstanten) Referenz auf auf die Foo-Instanz foo auf).

    Grüße...

    Heiko



  • bwbg schrieb:

    Foo foo(12);
    Foo bar = foo++;
    

    möglich sind (die Zweite Zeile ruft den Kopierkonstruktor von Foo mit der (konstanten) Referenz auf auf die Foo-Instanz foo auf).

    Für die zweite Zeile benötigst du aber einen anderen Operator - operator++() ist das Präfix-Inkrement ++foo, operator++(int) ist das Postfix-Inkrement foo++ (der int-Parameter dient nur zur Unterscheidung und wird mit 0 gefüllt).



  • So also erstmal ganz allgemein: Ich möchte einfach nur, dass ++ umgedreht wird.
    Und das Template wollte ich benutzen, damit ich nicht für jeden Zahl-Typ (int, float, double, etc.) den Operator überladen muss.

    EDIT: ich habe mir auch schon etliche tutorials dazu angeguckt, aber ich glaube ich bin zu blöd dafür...



  • BitWax schrieb:

    Und das Template wollte ich benutzen, damit ich nicht für jeden Zahl-Typ (int, float, double, etc.) den Operator überladen muss.

    Nochmal: Du kannst den operator++ für Zahlen-Typen garnicht überladen.



  • BitWax schrieb:

    Und das Template wollte ich benutzen, damit ich nicht für jeden Zahl-Typ (int, float, double, etc.) den Operator überladen muss.

    Du kannst Operatoren nicht für Build-in Typen überladen - mindestens ein Operand muß von einem selbstdefinierter Typ sein (beim Inkrement gibt es nur einen Operanden).



  • Hmmm. Also so wie ich da verstanden hatte (aus den Tutorials her) steht als erstes der Linke Bezeichner. Danach kommt der Operator und in den Klammern dann der rechte Bezeichner. Also:

    LINKS klasse::operator= (RECHTS)
    {
        LINKS = LINKS - RECHTS;
        return LINKS;
    }
    

    Das Beispiel soll nichts anderes machen, als das wenn man zum Beispiel schreibt:

    int a = 5, b = 3;
    a = b;
    

    Dass a dann eben gleich 2 ist.

    EDIT: die geschichte natürlich noch auf eine Klasse angewendet.



  • so natürlich ist das nicht, denn unter c++ sind die datentypen keine eigenständigen klassen



  • ich verbesser das mal, eben auf eine klasse angewendet:

    LINKS& klasse::operator= (RECHTS)
    {
        LINKS = LINKS - RECHTS;
        return LINKS;
    }
    .
    .
    .
    klasse kl;
    kl.a = 5;
    kl.b = 3;
    
    kl.a = kl.b;
    


  • Vielleicht solltest du dir nochmal den Unterschied zwischen Typ und Variable ansehen. (oder reden wir hier von einer typlosen Scriptsprache mit C++ ähnlicherSyntax?)

    //als Methode
    //  linker Operand ist *this (Typ LINKS)
    //  rechter Operand ist r (Typ RECHTS)
    //  Rückgabe hat Typ ERGEBNIS
    ERGEBNIS LINKS::operator*(RECHTS r)
    {
      ERGEBNIS e = mult(*this,r);
      return e;
    }
    //bzw:
    //als globale Funktion
    ERGEBNIS operator*(LINKS l,RECHTS r)
    {
      ERGEBNIS e = mult(l,r);
      return e;
    }
    

    Und der operator= einer Klasse bezieht sich nicht auf Zuweisungen zwischen Membervariablen, sondern auf Zuweisungen der Klasse gesamt:

    klasse k1,k2;
    k1=k2;//hier greift op=
    


  • Achso! ich dachte das hier

    blabla::operator...

    muss eine klasse sein! zumindest blabla.



  • BitWax schrieb:

    Achso! ich dachte das hier

    blabla::operator...

    muss eine klasse sein! zumindest blabla.

    Strenggenommen (ohne Zusammenhang) muss blabla hier eine Klasse oder ein Namespace sein.



  • Ich habe das jetzt mal versucht, einen Operator global zu überladen:

    int operator+ (int l, int r)
    {
        return l - r;
    }
    

    und das sagt er mir beim compilieren:

    Error E2082 main.cpp 5: 'operator +(int,int)' must be a member function or have
    a parameter of class type
    

    und so probiere ich es

    int main ()
    {
        int a = 5;
        int b = 4;
    
        cout << a + b << endl;
    
        return 0;
    }
    

    Bitte nicht schlagen, wenns komplett falsch ist, aber das ist echt absolutes Neuland.



  • Auch für globale Operatorfunktionen gilt, was LordJaxom und ich vorhin gesagt haben:

    CStoll schrieb:

    BitWax schrieb:

    Und das Template wollte ich benutzen, damit ich nicht für jeden Zahl-Typ (int, float, double, etc.) den Operator überladen muss.

    Du kannst Operatoren nicht für Build-in Typen überladen - mindestens ein Operand muß von einem selbstdefinierter Typ sein (beim Inkrement gibt es nur einen Operanden).



  • auf deutsch: selbst wenn ich den global überladen will, muss immer eine eigene klasse/struktur damit verbunden werden?



  • Ja, oder anders gesagt: Der Compiler verbietet Dir aus gutem Grund, die Bedeutung von (z.B.) 1+1 zu ändern.



  • Schade! Eigentlich wollte ich ne DLL basteln, dort alle Operatoren verändern und die DLL dann rausgeben[/ironie]
    Naja, versteh schon warum, aber das nervt mich gerade ein bisschen...


Anmelden zum Antworten