Fragen zu Klasse und Operatorüberladung



  • Hallo,

    ich stell mien Fragen als Kommentare im Code

    //zum vergleich
    const int SIZE = 1;       //dies möchte ich benutzen bei *1
    const int COMPLETE = 2;
    
    class IntFeld
    {
      public:
         IntFeld(int firstNumber = 0);
         ~IntFeld();
    
         int operator[](int index);
    
         IntFeld& operator+=(const IntFeld& rhs);
         IntFeld& operator+=(const int newInt);
    
         bool operator==(const IntFeld& toCompare);
         bool operator<(const IntFeld& toCompare);
         bool operator>(const IntFeld& toCompare);
         bool operator<=(const IntFeld& toCompare);
         bool operator>=(const IntFeld& toCompare);
    
         int at(int index)const;
         int top()const;
         int first()const;
    
         void push_back(int newInt);
         void pop_back();
    
         int size()const;
         int capacity()const;
    
         bool isEqual(const IntFeld& toCompare,int comparemode); //*1 - als comparemode, ist das eine gute idee? je nachdem ob SIZE oder COMPLETE angeben, macht die funktion einen andren vergleich
    
      private:
         int*       m_data;
         int        m_index;
    
    };
    
    IntFeld operator+(const IntFeld& lhs,const IntFeld& rhs);   
    IntFeld operator+(const IntFeld& lhs,const int newInt);    //wieso kann ich diese operatoren nicht in der klasse deklarieren? Er sagt, das sie nur einen parameter haben sollen, aber wie würden diese dann aufgerufen?Bei + wird doch kein objekt verändert, kann mir das jemand erklären?
    

    hoffe mir kann jemand meine fragen erklären!



  • Klar kannst du einen Operator in einer Klasse definieren. In dem Fall wird der erste Operand über den this-Zeiger übergeben.

    Zu deinem *1: Die Fallunterscheidung könntest du per if() durchführen.



  • CStoll schrieb:

    Klar kannst du einen Operator in einer Klasse definieren. In dem Fall wird der erste Operand über den this-Zeiger übergeben.

    ja das ist mir klar, aber wie sieht dann der aufruf aus?

    bei dem ausserhalb (mit 2 parametern) wäre es doch so:

    IntFeld a(1);
    IntFeld b(2);
    IntFeld c;
    
    c = a+b;
    

    CStoll schrieb:

    Zu deinem *1: Die Fallunterscheidung könntest du per if() durchführen.

    auch das ist mir klar, ich wollte eher wissen, ob die vorgehensweise mit den const ints gut ist, das ich also es so benutzen kann:

    IntFeld a(1);
    IntFeld b(2);
    
    bool ok = b.isEqual(a,SIZE);
    

    oder wären enums oder so besser?(muss ich da aber nicht immer den klassenqualifizierer mit nennen? klasse::enum? oder wie benutze ich ein enum in klassen?



  • Für die Verwendung des Operators spielt es keine Rolle, ob du ihn als globale Funktion oder als Member definiert hast (naja fast, aber die Unterschiede sind hier nicht relevant).

    A: In der Klasse:

    class IntFeld
    {
    public:
      IntFeld operator+(const IntFeld& r) const
      {
        IntFeld tmp = *this;
        tmp+=r;
        return tmp;
      }
    };
    

    B: Als globale Funktion

    IntFeld operator+(const IntFeld& l, const IntFeld& r)
    {
      IntFeld tmp = l;
      tmp+=r;
      return tmp;
    }
    

    (ich verzichte mal auf mögliche Optimierungen des Codes, hier geht es um's Prinzip)

    In beiden Fällen ist der Compiler in der Lage, den Aufruf c=a+b; zu erkennen und der richtigen Operator-Funktion zuzuordnen.

    @equalTo:
    Ich würde da vermutlich einen enum verwenden. Falls es dich stört, den Klassennamen mit angeben zu müssen, kannst du ihn auch außerhalb der Klasse anlegen:

    enum CMode { SIZE, COMPLETE };
    class IntFeld
    {
    public:
      bool isEqual(const IntFeld& other,CMode mode);
    };
    


  • ok, das mit dem enum kann ich machen!
    und wo ist denn aber der unterschied zwischen op in klasse und ausserhalb, ich versteh es nicht ganz! 😞

    zeig mir mal ein beispiel, wo der unterschied wichtig ist bitte!



  • Ein Beispiel wäre, wenn du den Operator für eine andere Klasse bzw. einen anderen Typ überladen willst (Nicht bei allen Klassen will/kann man das reinschreiben, z.b. ostream).
    Außerdem ist außerhalb kein Überschreiben des Operators möglich.

    z.B.:

    // Achtung: pseudo code
    std::ostream& operator << (std::ostream& rStream, const IntFeld& rPrintee);
    // oder
    IntField operator +(int a, IntField);
    // bzw.
    
    class A
    {
    public:
        virtual A operator +(int n);
    };
    class B : public A
    {
    public:
        virtual A operator +(int n);
    };
    

    MfG
    DDR-RAM



  • Globale Operatoren mußt du in zwei Fällen verwenden:

    1. du hast keinen Zugriff auf die Klasse des linken Operanden (das betrifft z.B. die IO-Operatoren << und >> oder auch Build-Ins)
    2. Du willst eine Typumwandlung für den linken Operanden zulassen
    class Test
    {
    public:
      Test(int);//Typumwandlung per Ctor
      ...
    };
    
    Test t1;
    Test t2 = 5+t1;
    //globaler op+: wandelt 5 um und rechnet mit temporärer Variable
    //Member-op+: nicht zugelassen
    

    Aber meist ist es üblicher, die Operatoren in der Klasse anzulegen.


Anmelden zum Antworten