Bonjour,
J'ai une question concernant la rupture des invariants en C++. En général, on dit que les invariants s'appliquent à l'extérieur d'une classe : Meyer himself
Donc un objet est construit de façon à respecter ses invariants, ensuite chaque fois qu'une fonction est appelée en respect du contrat, les invariants sont toujours respectés lorsque l'appelant récupère l'objet.It describes a consistency property that every instance of the class must satisfy whenever it's observable from the outside
En revanche, à l'intérieur d'une fonction, l'invariant peut être momentanément rompu du moment qu'il est rétabli avant la fin de la fonction.
Soit une classe C, dans une fonction F1, au moment où un invariant est rompu, sémantiquement :
-> (1) F1 a-t-elle le droit d'appeler une méthode publique (non virtuelle) C::F2 sans rétablir les invariants ? J'aurais tendance à dire que non, car cette méthode étant publique, le respect des invariants est une précondition implicite.
-> (2) F1 a-t-elle le droit d'appeler une méthode privée (non virtuelle) C::F2 sans rétablir les invariants ? J'aurais tendance à dire que oui, car cette méthode étant privée, seule C peut l'appeler et éventuellement savoir qu'elle peut l'appeler sans respecter certains invariants. On est dans le cas où non 'observable from the outside".
-> (3) F1 a-t-elle le droit d'appeler une méthode protégée (non virtuelle) C::F2 sans rétablir les invariants ? Je ne sais pas trop quoi répondre car cette méthode n'est pas accessible à l'extérieur mais elle l'est par les classes dérivées.
Rajoutons l'héritage et supposons que C dérive de B :
-> (4) F1 peut-elle appeler une méthode publique (non virtuelle) de la classe B sans rétablir les invariants ? J'aurais envie d'avoir la même analyse que pour (1)
-> (5) F1 peut-elle appeler une méthode protégée (non virtuelle) de la classe B sans rétablir les invariants ? Idem qu'en (3), je ne sais pas trop quoi en penser.
Maintenant, supposons une classe D dérivant de C.
La résolution dynamique de l'appel d'une fonction virtuelle ne tient pas compte de la visibilité de la fonction virtuelle, ni dans la classe C, ni dans la classe dérivée D. D'où
-> (6) F1 peut-elle appeler une méthode virtuelle sans rétablir les invariants ?
-> (7) Faut-il dissocier fonctions virtuelles pures ou non ?
En fait, les questions (3), (5) et (6) ( (7) devrait être une conséquence de la réponse aux trois premières), à mon avis, trouvent leur réponse dans une question plus générale :
Si la réponse est oui, alors F1 doit rétablir les invariants dans les cas (3), (5) et (6) et il n'y a pas de différence que les fonctions soit virtuelles pures ou juste virtuelles.Est-ce qu'une classe de base B ou une classe dérivée D de la classe C est externe à C ?
Si la réponse est non, alors quelles sont les conditions valides pour les différents appels ?
Et, là j'avoue que je ne sais pas trop quoi répondre. J'ai envie d'avoir une approche 'forte' (répondre 'oui') qui implique alors que :
-> (8) Pour un appel d'une fonction non virtuelle d'une classe de base, les invariants de la classe de base et de la classe C doivent être respectés ;
-> (9) Pour un appel d'une fonction virtuelle (donc potentiellement d'une spécialisation de la classe dérivée), les invariants de la classe C doivent être respectés.
On pourrait avoir une approche plus souple concernant (8) en disant que seuls les invariants de la classe de base doivent être respectés. Mais si celle-ci fait appel à une méthode virtuelle, elle peut être amenée à appeler une fonction d'une classe dérivée sans respecter les invariants. Quid ?
Le pattern NVI a l'avantage de dissocier le contrat de la classe vis-à-vis de l'extérieur stricto-sensu d'un côté et de classes dérivées de l'autre. En ce sens, l'utilisation de ce pattern peut apporter des souplesses : le non-respect d'un invariant peut faire partie du contrat de la fonction virtuelle. En généralisant un peu, est-ce que la portée de la fonction virtuelle si elle est ignorée syntaxiquement ne devrait pas être prise en compte dans le contrat pour savoir quelle politique appliquée sur les invariants ? Difficile de répondre car une classe dérivée peut changer la portée d'une fonction.
Je n'ai pas vraiment trouvé de réponses satisfaisantes à ces interrogations. J'aurais aimé connaître votre vision de cet aspect ?
Je ne sais pas si j'ai été suffisamment clair...
![]()
Partager