Hello.
C’est cool ce que je vois.
Mes petits pinaillages.
La solution pour respecter nos invariants s’appelle l’encapsulation. Plutôt que de laisser nos attributs librement modifiables par le premier venu, nous allons les protéger, les masquer
Je ne suis pas d’accord avec le terme "masquer", surtout aussi vite. Je préfère p.ex: "les enrober d’une couche protectrice (ou pourquoi on parle d’en- capsul -ation). Techniquement, en C++ et les langages qui s’en sont inspiré, on fait ça en cachant/masquant les informations/données qui participent à l’invariant, voire toutes les données.". (vu que Python ou Eiffel ont suivi un autre chemin)
Fraction pow(Fraction const & fraction, int puissance)
Cette fonction devrait être statique. Vu que c’est un peu tôt pour en parler, je la supprimerai. Perso, j’aurai juste fourni Fraction Fraction::pow(int) const
.
Cet exemple montre juste la construction par copie. Puisqu’on en parle au chapitre suivant…
Pas d’exception car on ne fait qu’initialiser deux entiers.
A ce compte là, on peut tout mettre en noexcept
. Mais n’est-ce pas trop tôt comme sujet?
définir comme explicit tout constructeur prenant un argument
Je formulerai plutôt la règle générale avec
définir comme explicit tout constructeur pouvant prendre un seul argument — au sens pouvant être appelé avec un seul paramètre réel
Un exemple que j’utilise en général pour explicit
, c’est les tableaux
void f(std::vector<double>);
...
f(42);
"Imaginez ce qu’il se passerait si le constructeur mono-argument entier des vecteurs étaient un constructeur de conversion, i.e. non explicite".
Au delà de la lisibilité, on encourt des risques de bugs. Cf les tristement célèbres
struct S {
S(std::string);
S(double);
};
bool operator==(S, S);
...
if ("toto"s == 42.5)