Bonjour.
J'essaie de définir une classe "safeUInt" (safe unsigned int) dont l'éventail de valeurs serait le même que celui du type "unsigned int" mais auquel il serait impossible de passer une valeur négative, la conversion implicite étant refusée par le compilateur.

J'ai essayé d'utiliser le mot-clé "explicit" dans le constructeur, mais cela semble ne servir à rien.

Voici le code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
}
Quelqu'un voit-il ce qui cloche ?
Merci d'avance.