Opérateurs

Nom C++ Sens
Binaire () [] -> ->
Unaire + - ++ -- ~ * & <-
Unaire new new[] delete delete[] (cast) ->
Binaire * / % ->
Binaire + - ->
Binaire << >> ->
Binaire == != ->
Binaire & ->
Binaire ^ ->
Binaire || ->
Binaire && ->
Binaire ->
Binaire = += -= *= /= %= &= ^= |= <<= >>= <-

Décomposition de comment une expression est gérer par l’ordinateur

((a+((f\times b)\times c)) = (d = (++a)))

flowchart TD
1[=] --> 2 & 3
2[+] --> 4 & 5
3[=] --> 8 & 9
4[a]
5[*] --> 6 & 7[c]
6[f]
7[b]
8[d]
9[++] --> 10
10[a]

Test d’opérateurs testOp.cpp :

#include<iostream>

class Frac {
    int num;
    int den;
    public:
        Frac(int n, int d) {
            num = n;
            den = d;
        }
        
        void afficher(void) {
            std::cout << "num:" << num << ", den:" << den << std::endl;
        }

        Frac operator +(const Frac& a) const {
            Frac retour(0, 0);
            retour.num = a.num * den + num * a.den;
            retour.den = a.den * den;

            return retour;
        }

        friend Frac operator *(const Frac& a, const Frac& b);
};

Frac operator *(const Frac& a, const Frac& b) {
    Frac retour(a.num, a.den);
    retour.num *= b.num;
    retour.den *= b.den;

    return retour;
}

int main(void) {
    Frac const a(3, 2);
    Frac const b(1, 4);
    Frac c = a + b; // Frac = a.operator + (b);
    c.afficher();

    return 0;
}

Il faut penser à modifier l’opérateur d’affectation quand on créer une classe qui utilises de la mémoire (pour renvoyer une copie d’un élément…) et éviter de perdre un élément.
Exemple depuis l’exemple précédent :

Frac operator =(const Frac& b) {
    std::cout << "opérateur affectation" << std::endl;
    num = b.num;
    den = b.den;

    return *this;
}

Ainsi dans le main…

c = a; // on garde a et on a un nouveau c
void maFonction(Frac a) {
    a.afficher();
}

int main(void) {
    maFonction(3);
}

Dans ce cas, le compilateur ne rale pas, malgré que la fonction maFonction prenne un Frac et non un int, car il y a une conversion implicite de int vers Frac.

Bilan

Lorsqu’un classe (ex: class A { ... };)est définie, alors par défaut est construit :

Remarque

class A {
    A(void) = delete; // constructeur
    ~A(void) = delete; // desctucteur
    void operator =(...) = delete; // affectation
    A(const A& a) = delete; // recopie
};
class A { ... };
A operator +(A a, A b)  {// fonction qui renvoie un A
    ...
}
int main() {
    A a;
    A b;
    ...
    ... a + b ... sera transformé en : ... operator +(a, b) ...
    ...
    return ...;
}
class A {
    ...
    A operator +(A a) { // un seul paramètre car l'autre est *this
        ...
        ...
        return ...;
    }
};