begin process at 2012 05 27 21:12:30
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Tutoriaux

 > UTILISATION DE LA TECHNIQUE DES "TRAITS"

UTILISATION DE LA TECHNIQUE DES "TRAITS"


 Information sur la source

Note :
Aucune note
Catégorie :Tutoriaux Classé sous :trait Niveau :Débutant Date de création :21/04/2006 Date de mise à jour :21/04/2006 14:04:36 Vu / téléchargé :4 424 / 112

Auteur : exar

Ecrire un message privé
Site perso
Commentaire sur cette source (0)
Ajouter un commentaire et/ou une note

 Description

Remarque préliminaire: les classes utilisées dans cet exemple n'effectuent aucun contrôle et ne gèrent aucune exception.  Elles ne sont données qu'en exemple.
Les "traits" permettent de définir les caractéristiques de types afin de pouvoir généraliser leur utilisation.
Imaginons que nous voulions définir une classe template contenant des données que nous appellerons "Variable".
Nous pouvons la définir comme suit:

template<class T>
class Variable{
   friend operator==(const Variable<T>& v1, const Variable<T>& v2){
      return (v1._donnee==v2.donnee);
   }
private:
   T _donnee;
public:
   Variable(T);
   Variable(const Variable<T>&);
   ~Variable();
   Variable<T>& operator=(const Variable<T>&);
   Variable<T>& operator=(const T&);
   T valeur()const;
};

voici son implémentation:

template<class T>
Variable<T>::Variable(T donnee)
   :_donnee(donnee){

}

template<class T>
Variable::Variable(const Variable<T>& v)
   :_donnee(v._donnee){

}

template<class T>
Variable<T>::~Variable(){

}

template<class T>
Variable<T>& Variable<T>::operator=(const Variable<T>& v){
   _donnee=v._donnee;
}

template<class T>
T valeur()const{
   return _donnee;
}

Si nous utilisons un type int ou float, par exemple, pas de problème.  Mais qu'advient-il si on tente d'utiliser un type char*, par exemple ?
Là intervient la technique des traits.

Déclarons la structure suivante:

template<class T>
struct Trait{
   typedef T trait_type;
   void assign(T&, T);
   bool eq(T, T);
   bool ls(T, T);
   bool gt(T, T);
   void free(T&);
};

Voici son implémentation:

template<class T>
void Trait<T>::assign(T& t1, T t2){
   t1=t2;
}

template<class T>
bool Trait<T>::eq(T, T){
   return (t1._donnee==t2._donnee);
}

template<class T>
bool Trait<T>::ls(T, T){
   return (t1._donnee<t2._donnee);
}

template<class T>
bool Trait<T>::gt(T, T){
   return(t1._donnee>t2._donnee);
}

template<class T>
void Trait<T>::free(T&){
   //rien à faire
}

Nous avons vu que le type char*, par exemple, pouvait poser problème.  Spécialisons donc la struct pour le type char*:

template<>
void Trait<char*>::assign(char*& s1, char* s2){
   if(s1)
      delete [] s1;
   s1=new char[strlen(s2)+1];
   strcpy(s1, s2);
}

template<>
bool Trait<char*>::eq(char* s1, char* s2){
   return (strcmp(s1, s2)==0);
}

template<>
bool Trait<char* s1, char* s2){
   return (strcmp(s1, s2)<0);
}

template<>
bool Trait<char*>::gt(char* s1, char* s2){
   return (strcmp(s1, s2)>0);
}

template<>
void Trait<char*>::free(char* s){
   // Ici, quelque chose à faire !
   delete [] s;
   s=NULL;
}

Nous pouvons donc redéfinir notre classe variable comme suit:

template<class T, class traits=Trait<T> >
class Variable{
   friend bool operator==(const Variable<T, traits>& v1, const Variable<T, traits>& v2){
      traits t;
      return (t.eq(v1._donnee, v2._donnee));
   }
private:
   traits _t;
   T _donnee;
public:
   Variable(T);
   Variable(const Variable<T, traits>&);
   ~Variable();

   Variable<T, traits>& operator=(const Variable<T, traits>&);
   Variable<T, traits>& operator=(const T&);

   T& valeur()const;
};

Voici l'implémentation:

template<class T, class traits>
Variable<T, traits>::Variable(T donnee){
   _t.assign(_donnee, donnee);
}

template<class T, class traits>
Variable<T, traits>::Variable(Variable<T, traits>& v){
   _t.assign(_donnee, v._donnee);
}

template<class T, class traits>
Variable<T, traits>::~Variable(){
   _t.free(_donnee);
}

template<class T, class traits>
Variable<T, traits>& Variable<T, traits>::operator=(const Variable<T, traits>& v){
   _t.assign(_donnee, v._donnee);
}

template<class T, class traits>
Variable<T, traits>& Variable<T, traits>::operator=(const T& donnee){
   _t.assign(_donnee, donnee);
}

template<class T, class traits>
T& Variable<T, traits>::valeur()const{
   return _donnee;
}

Un simple petit test démontre que maintenant, avec le type char*, notre classe Variable fonctionne !

Imaginons que nous ajoutions une classe Date de notre cru.

class Date{
private:
   int _jour;
   int _mois;
   int _annee;
public:
   Date();
   Date(int, int, int);
   Date(const Date&);
   ~Date();
   int getJour()const;
   int getMois()const;
   int getAnnee()const;
   void setJour(int);
   void setMois(int);
   void setAnnee(int);
   Date& operator=(const Date&);
};

Date::Date()
   :_jour(1), _mois(1), _annee(1901){

}

Date::Date(int jour, int mois, int annee)
   :_jour(jour), _mois(mois), _annee(annee){

}

Date::~Date{

}

int Date::getJour()const{
   return _jour;
}

int Date::getMois()const{
   return _mois;
}

int Date::getAnnee()const{
   return _annee;
}

void Date::setJour(int jour){
   _jour=jour;
}

void Date::setMois(int mois){
   _mois=mois;
}

void Date::setAnnee(int annee){
   _annee=annee;
}

Date& Date::operator=(const Date& d){
   _jour=d._jour;
   _mois=d._mois;
   _annee=d._annee;
}

Nous pouvons à nouveau spécialiser la struct Trait pour les dates:

template<>
bool Trait<Date>::eq(Date d1, Date d2){
   return ((d1.getJour()==d2.getJour())&&(d1.getMois()==d2.g etMois())&&(d1.getAnnee()==d2.getAnnee()));
}

Et ainsi de suite pour les autres opérateurs.

Il existe d'autres nombreuses possibilités, à vous de les explorer.

L'exemple fourni dans le ZIP est un peu plus complet, mais il peut être amélioré et complété.
Il fournit l'exemple d'une pile pouvant contenir les différents types décrits dans cet article.
Bonne chance !




 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

21 avril 2006 13:56:59 :
Explications
21 avril 2006 14:02:11 :
Correction
21 avril 2006 14:04:36 :
Re-correction

 Sources du même auteur

Source avec Zip CLASSE DE DATE LOCALISÉE (20 LANGUES)
Source avec Zip TRACEUR
Source avec Zip Source avec une capture LISTE CHAÎNÉE ORIENTÉE OBJET, BASÉE SUR LES TEMPLATES

 Sources de la même categorie

LISTER FICHIERS ET RÉPERTOIRES (MULTIPLATEFORME) par christophedlr
UTILISATION DES TYPELIST EN C++ par wyden
Source avec Zip Source avec une capture QCSSCOMPRESSOR par alphaone
AFFICHAGE D'UN TRIANGLE ISOCELE par nabche
Source avec Zip GESTION D'UNE BIBLOTHEQUE par leclerro19

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture DESSIN SUR ÉCRAN (TRÈS SIMPLE) par ordiman85

Commentaires et avis

Aucun commentaire pour le moment.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

horrible trait horizontaux [ par vladisback ] bonjour, je réalise actuellement mon premier programme utilisant l'opengl, j'affiche principalement des polygones transparent, j'utilise un double buf Recuperation de la longueur d'un trait [ par CoK 07 ] J'aimerai savoir comment je pourrai recup&#233;rer la longueur d'une ligne que je trace et la convertir en grandeur reelle car je suppose que la grand


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,421 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales