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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| class Tableau
{
public:
/* par défaut, on prévoit 10 éléments contigus
* ( c'est limite fixée de manière tout à fait arbitraire :D)
*/
Tableau():size_(10), nextpos_(0), ptr_(new int[10]){}
/* mais on laisse la possibilité à l'utilisateur d'en prévoir un
* nombre différent
*/
Tableau(size_t s):size_(s),nextpos_(0),ptr_(new int[s]){}
/* le constructeur par copie */
Tableau(Tableau const & rhs):size_(rhs.size_),nextpos_(rhs.nextpos_),
ptr_(new int[rhs.size_])
{
memcopy(ptr_,rhs.ptr_,size_);
}
/* et l'opérateur d'affectation Il utilise le fait que nous passons
* le tableau à affecter sous forme de valeur, ce qui implique,
* de facto la copie.
* Le principe mis en oeuvre est le copy 'n swap ;)
*/
Tableau & operator = (Tableau t)
{
std::swap(size_,t.size_);
std::swap(nextpos_,t.nextpos_);
std::swap(ptr_,t.ptr_);
return *this;
}
~Tableau()
{
delete[] ptr_;
ptr_=0;
}
/* on permet à l'utilisateur d'ajouter un élément en fin de tableau
*/
void push_back(int i)
{
/* en doublant chaque fois la taille du tableau si nous avons
* atteint la limite des éléments possibles, nous évitons
* de devoir le refaire à chaque insertion
*/
if(nextpos_==size_)
resize(size_*2);
ptr_[nextpos_]=i;
++nextpos_;
}
/* on permet à l'utilisateur de retirer le dernier élément du tableau
*/
void pop_back()
{
--nextpos_;
}
/* on pourrait aussi lui permettre d'en rajouter en début de tableau,
* voire d'insérer un élément entre deux éléments existants...
* Je ne présente pas ces fonctionnalités
*/
/* on permet à l'utilisateur d'accéder à une valeur grace à
* l'opérateur []
* sous la forme non constante
*/
int & operator[](size_t index){return ptr_[index];}
/* et sous la forme constante */
int const & operator[](size_t index){return ptr_[index];}
/* La fonction at fournit la même possibilité, mais avec un controle
* de l'index demandé (lance une exception "Overflow" à définir
* si l'index est hors des limites admises
*/
int & at(size_t index)
{
if(index>=nextpos_)
throw Overflow();
return ptr_[index];
}
int const & at() const
{
if(index>=nextpos_)
throw Overflow();
return ptr_[index];
}
/* cette fonction permet de redimensionner le tableau */
void resize(size_t newsize)
{
/* trois possibilités s'offrent à nous:
* - soit on rajoute des éléments potentiels,
* - soit on redimensionne afin d'en retirer
* - soit on ne change pas la taille
*/
/* si on ne change pas la taille, on ne fait simplement rien */
if(newsize!=size_)
{
/* il nous faut un tableau temporaire à la bonne taille */
int * temp=new int[newsize];
/* si la nouvelle taille est plus grande que le nombre
* d'éléments présents, nous copions nextpos_ elements
* du tableau d'origine vers le tableau temporaire
* la position suivante reste inchangée
*/
if(newsize>nexpos_)
{
memncpy(temp,ptr_,nextpos_*sizeof(int));
}
/* sinon, nous copions newsize éléments du tableau d'origine
* vers le tableau temporaire et
* la position suivante prend la valeur de newsize
*/
else
{
memncpy(temp,ptr_,newsize*sizeof(int));
nextpos_=newsize;
}
/* on termine en libérant la mémoire allouée au tableau
* d'origine
*/
delete [] ptr_;
/* en définissant la nouvelle taille
*/
size_=newsize;
/* et en assignant le tableau temporaire au pointeur réel
*/
ptr_=temp;
}
}
private:
size_t size_; // le nombre maximal d'éléments potentiel à
// un instant T
size_t nextpos_; // la position du prochain élément
int * ptr_; // le pointeur vers le tableau dont la mémoire est
// allouée dynamiquement
}; |
Partager