HOWTO · C++

Comment surcharger l'opérateur == en C++

Ceci est un tutoriel de programmation pour l'implémentation de la surcharge de l'opérateur == en C++.

Sur cette page

Une classe peut définir l’égalité en implémentant operator==. La fonction doit comparer les champs qui représentent la valeur de l’objet. L’exemple Employee ci-dessous compare un nom et un salaire, puis montre comment == signale des employés identiques et différents.

Surcharge d’opérateurs en C++

La surcharge d’opérateurs donne à un opérateur existant une signification pour un type défini par l’utilisateur, tel qu’une classe ou un struct. Une surcharge membre a couramment cette forme : return_type operator symbol(parameters). Par exemple, operator== est le nom de la fonction utilisée pour surcharger l’égalité.

Une surcharge doit impliquer au moins un type défini par l’utilisateur ; elle ne peut pas redéfinir une opération dont les opérandes sont tous des types intégrés tels que int ou char. Elle ne peut pas non plus changer la priorité d’un opérateur, son nombre d’opérandes ou son associativité. La syntaxe et l’expression familière restent les mêmes, de sorte que les appelants peuvent écrire first == second au lieu d’appeler directement une méthode de comparaison.

Certains opérateurs ne peuvent pas être surchargés, notamment ::, ., .*, ?: et sizeof. L’opérateur typeid ne peut pas non plus être surchargé.

Surcharger l’opérateur == en C++

Pour une classe, décidez quels champs définissent l’égalité avant d’écrire la fonction. Cette valeur Employee utilise à la fois name et salary ; si l’un ou l’autre diffère, les objets sont comparés comme inégaux. Une fonction membre const et un paramètre de référence const permettent la comparaison sans copier ni modifier l’un ou l’autre objet.

#include <iostream>
#include <string>

class Employee {
 public:
  Employee(std::string name, int salary)
      : name_(name), salary_(salary) {}

  bool operator==(const Employee& other) const {
    return name_ == other.name_ && salary_ == other.salary_;
  }

 private:
  std::string name_;
  int salary_;
};

int main() {
  const Employee first("David", 1000);
  const Employee same("David", 1000);
  const Employee different_salary("David", 1200);

  std::cout << (first == same ? "Equal" : "Not equal") << '\n';
  std::cout << (first == different_salary ? "Equal" : "Not equal") << '\n';
}
Equal
Not equal

La sortie affiche Equal lorsque les deux champs sélectionnés correspondent et Not equal lorsque le salaire diffère. Si la classe gagne par la suite un autre champ de valeur, incluez-le lorsque ce champ doit affecter l’égalité.

Surcharger l’opérateur == dans une hiérarchie de classes

Une fonction d’égalité de la classe de base ne vérifie que l’état de la classe de base inclus dans son implémentation. Elle peut être appelable pour des objets dérivés via le membre hérité, mais elle n’inspecte pas automatiquement les membres ajoutés par une classe dérivée. Un type dérivé n’a pas à définir l’égalité, sauf si sa propre sémantique de comparaison doit inclure un état supplémentaire.

Par exemple, si A stocke foo et définit bool operator==(const A& other) const, alors cette fonction compare foo. Si B : public A ajoute bar, définissez une comparaison B lorsque l’égalité pour B doit inclure bar : son résultat peut combiner A::operator==(static_cast<const A&>(other)) avec bar == other.bar. Cela compare explicitement la portion de base et le champ dérivé. Lorsqu’une surcharge dérivée porte le même nom, elle peut masquer les surcharges de la base lors de la recherche ordinaire ; utilisez un ensemble de surcharges délibéré si les deux comparaisons doivent être disponibles.

Les types statiques des opérandes de l’expression déterminent quelles surcharges participent. Pour des références de base polymorphes, une comparaison de la base compare toujours la vue de la base ; elle ne découvre ni ne compare dynamiquement les membres dérivés. L’égalité à travers une hiérarchie polymorphe a donc besoin d’une politique explicite quant à savoir si des types dynamiques différents peuvent être comparés comme égaux, avec un comportement concordant dans les deux ordres d’opérandes. Gardez la règle cohérente afin que l’égalité reste symétrique et reflète les valeurs que votre type promet de représenter.