Exemple de surcharge des opérateurs

De Appmethod Topics
Aller à : navigation, rechercher

Remonter à Présentation de la surcharge des fonctions opérateurs - Index

L'exemple suivant étend la classe complex pour créer des vecteurs de type complexe. La plupart des opérateurs les plus utiles sont surchargés pour pouvoir donner aux opérations mathématiques personnalisées une syntaxe logique.

Voici certaines des solutions illustrées dans cet exemple :

  • Le constructeur par défaut est défini. Le constructeur par défaut n'est fourni par le compilateur que si vous ne l'avez pas défini, lui ni un autre constructeur.
  • Le constructeur copie est défini explicitement. En règle générale, le compilateur fournit un constructeur si vous n'en avez défini aucun. Nous vous conseillons de définir le constructeur copie si vous devez surcharger l'opérateur d'affectation.
  • L'opérateur d'affectation est surchargé. Si vous ne le surchargez pas, le compilateur appelle un opérateur d'affectation lorsque c'est nécessaire. En surchargeant l'affectation de types cvector, vous spécifiez précisément les actions à entreprendre. Notez que les classes dérivées ne peuvent pas hériter de l'opérateur d'affectation.
  • L'opérateur d'accès est défini comme une fonction membre (nécessaire en cas de surcharge) qui n'a qu'un seul argument. La version const garantit que l'argument de l'appelant ne sera pas modifié (très utile lors d'une copie ou d'une affectation). Cet opérateur doit contrôler que la valeur d'index reste dans la fourchette de valeurs (c'est le bon emplacement pour implémenter la gestion des exceptions).
  • L'opérateur d'addition est défini comme une fonction membre. Il n'autorise l'addition que pour les types cvector. L'addition doit toujours vérifier que les tailles des opérandes sont compatibles.
  • L'opérateur de multiplication est déclaré comme friend. Cela permet de définir l'ordre des opérandes. Si vous tentez d'inverser l'ordre des opérandes, une erreur de compilation se produit.
  • L'opérateur d'insertion de flux est surchargé pour afficher un cvector. Les grands objets qui ne s'affichent pas correctement dans un écran de taille limitée nécessitent une stratégie d'affichage différente.

Exemple de source



 /* COMMENT ETENDRE LA CLASSE complex ET SURCHARGER LES OPERATEURS REQUIS */ */ complexcomplexcomplex
 #include <complex>  // Cela inclut iostream
 using namespace std;
 // VECTEURS COMPLEXES
 template <class T>
 class cvector {
    int size;
    complex<T> *data;
 public:
    cvector() { size = 0; data = NULL; };
    cvector(int i = 5) : size(i) {    // TAILLE DU VECTEUR PAR DEFAUT.
       data = new complex<T>[size];
       for (int j = 0; j < size; j++)
            data[j] = j + (0.1 * j);  // INITIALISATION ARBITRAIRE.
       };
    /* CETTE VERSION EST APPELEE DANS main() */
    complex<T>& operator [](int i) { return data[i]; };
    /* CETTE VERSION EST APPELEE DANS L'OPERATEUR D'AFFECTATION ET COPIE LE CONSTRUCTEUR */
    const complex<T>& operator [](int i) const { return data[i]; };
    cvector operator +(cvector& A) {  // OPERATEUR D'ADDITION
       cvector result(A.size);  // NE MODIFIE PAS L'ORIGINAL
       for (int i = 0; i < size; i++)
           result[i] = data[i] + A.data[i];
       return result;
       };
    /* LA MULTIPLICATION scalar * vector N'ETANT PAS COMMUTATIVE, L'ORDRE
       DES ELEMENTS DOIT ETRE SPECIFIE. LA FONCTION OPERATEUR AMIE REND FIABLE
       LE PROCEDE DE MULTIPLICATION. */
    friend cvector operator *(T scalar, cvector& A) {
       cvector result(A.size);  // NE MODIFIE PAS L'ORIGINAL
       for (int i = 0; i < A.size; i++)
         result.data[i] = scalar * A.data[i];
       return result;
       }
    /* L'OPERATEUR D'INSERTION DE FLUX */
    friend ostream& operator <<(ostream& out_data, cvector& C) {
       for (int i = 0; i < C.size; i++)
            out_data << "[" << i << "]=" << C.data[i] << "   ";
       cout << endl;
       return out_data;
       };
    cvector( const cvector &C ) {  // CONSTRUCTEUR DE COPIE
       size = C.size;
       data = new complex<T>[size];
       for (int i = 0; i < size; i++)
            data[i] = C[i];
      }
    cvector& operator =(const cvector &C) { // OPERATEUR D'AFFECTATION.
       if (this == &C) return *this;
       delete[] data;
       size = C.size;
       data = new complex<T>[size];
       for (int i = 0; i < size; i++)
           data[i] = C[i];
       return *this;
    };
    virtual ~cvector() { delete[] data; }; // DESTRUCTEUR
    };
 int main(void) { /* QUELQUES OPERATIONS AVEC LES VECTEURS complex. */
    cvector<float> cvector1(4), cvector2(4), result(4);
    // CREE DES VALEURS complex ET LES AFFECTE AUX VECTEURS complex
    cvector1[3] = complex<float>(3.3, 102.8);
    cout << "Voici cvector1 :" << endl;
    cout << cvector1;
    cvector2[3] = complex<float>(33.3, 81);
    cout << "Voici cvector2 :" << endl;
    cout << cvector2;
    result = cvector1 + cvector2;
    cout << "Résultat de l'addition des vecteurs :" << endl;
    cout << result;
    result = 10 * cvector2;
    cout << "Résultat de 10 * cvector2 :" << endl;
    cout << result;
    return 0;
    }



Sortie



 Voici cvector1 :
 [0]=(0, 0)   [1]=(1.1, 0)   [2]=(2.2, 0)   [3]=(3.3, 102.8)
 Voici cvector2 :
 [0]=(0, 0)   [1]=(1.1, 0)   [2]=(2.2, 0)   [3]=(33.3, 81)
 Résultat de l'addition des vecteurs :
 [0]=(0, 0)   [1]=(2.2, 0)   [2]=(4.4, 0)   [3]=(36.6, 183.8)
 Résultat de 10 * cvector2 :
 [0]=(0, 0)   [1]=(11, 0)   [2]=(22, 0)   [3]=(333, 810)