1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
// TypesSurs.cpp Définit une classe de nombres naturels, dont l'éventail de valeurs
// est le même que pour les unsigned int, mais dont le compilateur refuse l'instantiation à partir d'une valeur négative.
// On dirait que ça ne va pas.
// (le compilateur accepte une valeur négative et fait une conversion imlicite).
#include <iostream>
#include <climits>
#include <cstdlib> // Pour la fonction exit(0).
using std::cout;
using std::cin; // Je vais essayer de m'en servir pour empêcher la fenêtre de console de se
// fermer immédiatement.
using std::endl;
class safeUInt
{
public:
explicit safeUInt(unsigned int = 0); // constructeur de création. Le mot-clé "explicit" empêche le compilateur
// d'accepter autre chose qu'un "unsigned int". En fait, ça ne marche pas : Dev-C++ accepte avec un avertissement
// et Visual C++ 6 n'envoie même pas d'avertissement.
// On va expliciter le constructeur de copie, bien que ce ne soit pas nécessaire dans ce cas.
safeUInt(const safeUInt& );
void print() const; // const sert à ce que print ait accès aux objets déclarés comme constants.
// On va expliciter l'opérateur surchargé d'affectation, bien que dans ce cas ce ne soit pas nécessaire. (Rappel : on ne peut surcharger = que par une fonction membre; quand un opérateur binaire est surchargé par une fonction membre, c'est l'opérande gauche qui est censé être désigné par this; Deitel, p. 528.)
safeUInt& operator=(const safeUInt& );
private:
unsigned int sanssigne;
};
safeUInt::safeUInt(unsigned int i) // Constructeur de création. L'argument par défaut
// est indiqué dans le prototype.
{
// Si on passe une valeur négative pour i, le compilateur ne risque-t-il pas d'accepter
// et de faire une conversion implicite ? J'ai mis "explicit" dans le constructeur, mais
// on dirait que cela ne sert à rien.
sanssigne = i;
}
// On va expliciter le constructeur de copie, bien que ce ne soit pas nécessaire dans ce cas.
safeUInt::safeUInt(const safeUInt& n)
{ sanssigne = n.sanssigne;
}
// On va expliciter l'opérateur surchargé d'affectation, bien que dans ce cas ce ne soit pas nécessaire.
safeUInt& safeUInt::operator=(const safeUInt& n)
{
sanssigne = n.sanssigne;
return *this;
}
void safeUInt::print() const
{ cout << sanssigne;
} // const sert à ce que la fonction membre print ait accès aux objets déclarés comme constants.
int main()
{
int entreeBidon; // Recevra le cin qui sert à empêcher la fenêtre de console
// de se fermer immédiatement.
cout << "le safeUInt(-1) vaut : " << endl;
safeUInt(-1).print(); // Le compilateur l'accepte, avec un avertissement dans Dev-C++
// et sans avertissement dans Visual C++ 6..
cout <<"\nTapez un chiffre pour fermer cette fenêtre." << endl; // Ceci n'est pas nécessaire si on lance
// le programme à partir de l'IDE de Visual C++ (cela fait même, dans ce cas, double emploi
// avec "Press any key to continue", mais cela me semble nécessaire si on le lance à partir de l'IDE de Dev-C++
cin >> entreeBidon;
return 0;
} |
Partager