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

Code

 > 

Tutoriaux

 > UTILISATION DES TYPELIST EN C++

UTILISATION DES TYPELIST EN C++


 Information sur la source

Note :
Aucune note
Catégorie :Tutoriaux Classé sous :TypeList, Template, Class, Object, Objet Niveau :Expert Date de création :20/08/2011 Date de mise à jour :21/08/2011 19:37:14 Vu :1 950

Auteur : wyden

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

 Description

==========================
Note admin codes-sources:
==========================

ATTENTI ON:
Ce code est un exemple de ce qu'il est possible de faire avec des templates. Néanmoins, ce code NE doit PAS être utilisé. En effet, tous les effets que ce code émule sont disponibles dans le langage. "dynamic_cast" et "typeid" se charge déjà de le faire, et le font bien mieux.

En C++ propre, tout ce code tiendrait en 3 lignes (voir même en un mot "dynamic_cast"):

#include <iostream>

template <typename CastType, typename ObjType>
bool isInstanceOf(ObjType obj)
{
  return dynamic_cast<CastType>(obj);
}

struct A {};
struct B : public A {};
struct C {};

int main()
{
  A a;
  B b;
  C c;
  C* null = 0;

  std::cout << std::boolalpha
    << isInstanceOf<A*>(&a) << std::endl // true
    << isInstanceOf<A*>(&b) << std::endl // true
    << isInstanceOf<B*>(&b) << std::endl // true
    << isInstanceOf<C*>(&c) << std::endl // true
    << isInstanceOf<C*>(null) << std::endl; // false

  isInstanceOf<A*>(&c); // Ne compilera pas ! Et heureusement :)

  return 0;
}

==========================

Ce code permet de créer une mécanique qui imite le dynamic_cast. Le seul but est de montrer ce que l'on peut faire avec des templates.

Exemple : 'MyObject' est un objet générique, Les autres objets que l'on créera hériteront de cet objet.

MyClass1 heritera de MyObject
MyClass2 heritera de MyObject

etc, etc

Ainsi on peu générer automatiquement l'arborescence d'un objet, verifier s'il est bien une instance d'un objet parent etc etc.

Par exempl :

class MyClass1 : public MyObject
{
/* ... */
};

class MyClass2 : public MyObject
{
/* ... */
};

MyObject* obj1 = new MyClass1();
MyObject* obj2 = new MyClass2();

cout << (obj1.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj1.instanceOf<MyClass2>() ? "true" : "false") << endl; //false
cout << (obj2.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj2.instanceOf<MyClass2>() ? "true" : "false") << endl; //false

On peut imaginer encore plus complex

class MyClass3 : public MyClass1
{
/* ... */
};

class Myclass4 : public MyClass2
{
/* ... */
};

MyObject* obj3 = new MyClass3();
MyObject* obj4 = new MyClass4();

cout << (obj3.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj3.instanceOf<MyClass2>() ? "true" : "false") << endl; //false
cout << (obj3.instanceOf<MyClass3>() ? "true" : "false") << endl; //true
cout << (obj3.instanceOf<MyClass4>() ? "true" : "false") << endl; //false

cout << (obj4.instanceOf<MyClass1>() ? "true" : "false") << endl; //false
cout << (obj4.instanceOf<MyClass2>() ? "true" : "false") << endl; //true
cout << (obj4.instanceOf<MyClass3>() ? "true" : "false") << endl; //false
cout << (obj4.instanceOf<MyClass4>() ? "true" : "false") << endl; //true

Voila, voir le code pour comprendre comment cela fonctionne.

Source

  • #include <string>
  • #include <iostream>
  • using namespace std;
  • template<class __type, class __parent>
  • struct TypeList
  • {
  • typedef __type type;
  • typedef __parent parent;
  • };
  • #define INTERFACE(CLASSNAME) public:\
  • typedef TypeList<CLASSNAME, CLASSNAME::type> type;\
  • static inline std::string ClassName()\
  • {\
  • return type::parent::type::ClassName()+"."#CLASSNAME;\
  • }\
  • virtual inline std::string className()\
  • {\
  • return type::parent::type::ClassName()+"."#CLASSNAME;\
  • }\
  • static CLASSNAME* cast(void* __object)\
  • {\
  • CLASSNAME* object = (CLASSNAME*)__object;\
  • if(object->instanceOf<CLASSNAME>())return object;\
  • else return 0;\
  • }\
  • private:
  • #define DEFINE_INTERFACE(CLASSNAME) public:\
  • typedef TypeList<CLASSNAME, CLASSNAME> type;\
  • static inline std::string ClassName()\
  • {\
  • return #CLASSNAME;\
  • }\
  • virtual inline std::string className()\
  • {\
  • return ClassName();\
  • }\
  • template<class __type>\
  • bool instanceOf()\
  • {\
  • int res = className().find(__type::ClassName());\
  • return res >= 0;\
  • }\
  • static CLASSNAME* cast(void* __object)\
  • {\
  • CLASSNAME* object = (CLASSNAME*)__object;\
  • if(object->instanceOf<CLASSNAME>())return object;\
  • else return 0;\
  • }\
  • private:
  • class MyObject
  • {
  • DEFINE_INTERFACE(MyObject)
  • };
  • class MyClass1 : public MyObject
  • {
  • INTERFACE(MyClass1)
  • };
  • class MyClass2 : public MyObject
  • {
  • INTERFACE(MyClass2)
  • };
  • #define AFFICHER(X) #X" = " << X
  • int main(int argc, char** argv)
  • {
  • MyObject object;
  • MyClass1 class1;
  • MyClass2 class2;
  • cout << object.className() << endl;
  • cout << class1.className() << endl;
  • cout << class2.className() << endl;
  • cout << endl;
  • cout << AFFICHER(object.instanceOf<MyObject>()) << endl;
  • cout << AFFICHER(class1.instanceOf<MyObject>()) << endl;
  • cout << AFFICHER(class2.instanceOf<MyObject>()) << endl;
  • cout << endl;
  • cout << AFFICHER(object.instanceOf<MyClass1>()) << endl;
  • cout << AFFICHER(class1.instanceOf<MyClass1>()) << endl;
  • cout << AFFICHER(class2.instanceOf<MyClass1>()) << endl;
  • cout << endl;
  • cout << AFFICHER(object.instanceOf<MyClass2>()) << endl;
  • cout << AFFICHER(class1.instanceOf<MyClass2>()) << endl;
  • cout << AFFICHER(class2.instanceOf<MyClass2>()) << endl;
  • cout << endl;
  • cout << AFFICHER(MyObject::cast(&object)) << endl;
  • cout << AFFICHER(MyClass1::cast(&object)) << endl;
  • cout << AFFICHER(MyClass2::cast(&object)) << endl;
  • cout << endl;
  • cout << AFFICHER(MyObject::cast(&class1)) << endl;
  • cout << AFFICHER(MyClass1::cast(&class1)) << endl;
  • cout << AFFICHER(MyClass2::cast(&class1)) << endl;
  • cout << endl;
  • cout << AFFICHER(MyObject::cast(&class2)) << endl;
  • cout << AFFICHER(MyClass1::cast(&class2)) << endl;
  • cout << AFFICHER(MyClass2::cast(&class2)) << endl;
  • return 0;
  • }
#include <string>
#include <iostream>

using namespace std;

template<class __type, class __parent>
struct TypeList
{
    typedef __type type;
    typedef __parent parent;
};

#define INTERFACE(CLASSNAME) public:\
    typedef TypeList<CLASSNAME, CLASSNAME::type> type;\
    static inline std::string ClassName()\
    {\
        return type::parent::type::ClassName()+"."#CLASSNAME;\
    }\
    virtual inline std::string className()\
    {\
        return type::parent::type::ClassName()+"."#CLASSNAME;\
    }\
    static CLASSNAME* cast(void* __object)\
    {\
        CLASSNAME* object = (CLASSNAME*)__object;\
        if(object->instanceOf<CLASSNAME>())return object;\
        else return 0;\
    }\
    private:

#define DEFINE_INTERFACE(CLASSNAME) public:\
    typedef TypeList<CLASSNAME, CLASSNAME> type;\
    static inline std::string ClassName()\
    {\
        return #CLASSNAME;\
    }\
    virtual inline std::string className()\
    {\
        return ClassName();\
    }\
    template<class __type>\
    bool instanceOf()\
    {\
        int res = className().find(__type::ClassName());\
        return res >= 0;\
    }\
    static CLASSNAME* cast(void* __object)\
    {\
        CLASSNAME* object = (CLASSNAME*)__object;\
        if(object->instanceOf<CLASSNAME>())return object;\
        else return 0;\
    }\
    private:

class MyObject
{
    DEFINE_INTERFACE(MyObject)
};

class MyClass1 : public MyObject
{
    INTERFACE(MyClass1)
};

class MyClass2 : public MyObject
{
    INTERFACE(MyClass2)
};

#define AFFICHER(X) #X" = " << X

int main(int argc, char** argv)
{
    MyObject object;
    MyClass1 class1;
    MyClass2 class2;

    cout << object.className() << endl;
    cout << class1.className() << endl;
    cout << class2.className() << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyObject>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyObject>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyObject>()) << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyClass1>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyClass1>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyClass1>()) << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyClass2>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyClass2>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyClass2>()) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&object)) << endl;
    cout << AFFICHER(MyClass1::cast(&object)) << endl;
    cout << AFFICHER(MyClass2::cast(&object)) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&class1)) << endl;
    cout << AFFICHER(MyClass1::cast(&class1)) << endl;
    cout << AFFICHER(MyClass2::cast(&class1)) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&class2)) << endl;
    cout << AFFICHER(MyClass1::cast(&class2)) << endl;
    cout << AFFICHER(MyClass2::cast(&class2)) << endl;


    return 0;
}

 Conclusion

Je pense que cela peut vous servir.


 Historique

20 août 2011 05:54:21 :
Rien d'important

 Sources du même auteur

Source avec Zip POPUP QT ANIMER (ANIMATION DU MEME STYLE QUE LES POPUP DE WI...

 Sources de la même categorie

LISTER FICHIERS ET RÉPERTOIRES (MULTIPLATEFORME) par christophedlr
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
[PSP]HELLO WORLD par Mario1095

 Sources en rapport avec celle ci

Source avec Zip LIBRAIRIE JSON C++ par ordiman85
Source avec Zip POINTEUR INTELLIGENT par DrMckey
Source avec Zip TEMPLATES C/C++ POUR VS 2010 par BruNews
Source avec Zip CLASS SIMPLE POUR LIRE DES FICHIER *.INI par lglandeur
Source avec Zip Source avec une capture [C++/WIN32] COMPRESSEUR/DECOMPRESSEUR LZW par yann_lo_san

Commentaires et avis

Commentaire de CptPingu le 20/08/2011 23:27:14 administrateur CS

Bonjour.

Je ne sais pas trop par quoi commencer. Il y a plein de choses qui me gênent dans ce code.

Je ne vois pas l'utilité d'avoir recodé un système déjà existant en moins bien. Quel intérêt quand on a un dynamic_cast et des typeid ? (http://en.wikipedia.org/wiki/Typeid). On peut déjà faire tout ce que tu fais sans ajouter d'instructions intrusives dans son code.

De plus, au niveau architecture logiciel, dès le moment où toute classe hérite d'une super classe, c'est qu'il y a 99% de chance que la conception soit mauvaise.
J'ai aussi du mal à comprendre pourquoi il y a autant de macro, alors qu'une bonne partie du code aurait pu être écrite sous la forme de template.
Enfin, avoir des méthodes au nom identique mais à la casse différente, c'est très très risqué, et source d'ambiguïtés. D'ailleurs pourquoi avoir deux fois la même méthode dans ta première classe ?

Au niveau du code lui même, j'ai quelque remarques:
- Évite les using namespace, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- En C++, quand une méthode prend en argument un void*, c'est très très louche. On utilise généralement une méthode template pour éviter cela.
- Utilise des cast C++ et non des casts C. Le cast C est un fourre-tout qui ne te permet pas d'avoir un contrôle sur le type de cast que tu fais (renseigne toi sur: reinterpret_cast, static_cast, et dynamic_cast). Ici j'aurais plutôt fait un static_cast.
- Pour savoir de manière portable si la recherche dans un std::string a réussi, on ne regarde pas si res >= 0 mais si res != std::string::npos. D'ailleurs la méthode find renvoie normalement dans la plupart des implémentations de la STL, un size_t qui est non signé (donc récupérer cela avec un int signé c'est moyen).
- Pas besoin de else après un return (le return est débranchant)
- Au lieu de faire des MyObject::cast(&class1) ? "true" : "false" utilise directement des: std::boolalpha << MyObject::cast(&class1)
- Enfin, au lieu de faire des milliards de std::cout, n'en fait qu'un seul et chaîne tes actions...
Ex:
cout << object.className() << endl;
cout << class1.className() << endl;
cout << class2.className() << endl;

Devient:
std::cout << object.className() << std::endl
          << class1.className() << std::endl
          << class2.className() << std::endl;


Pour conclure, si ton but est uniquement de montrer une technique à travers un exemple, précise que cet exemple ne doit pas être utilisé en production, mais qu'il faut privilégier les mécanismes déjà existant du langage.
Ce sont ici des débutants qui lisent ces codes, et ça serait dommage qu'ils pensent que c'est la bonne méthode pour vérifier si une classe héritent d'une autre. (Soit dit en passant, si le programme est bien conçu, on n'a jamais besoin de savoir si une classe hérite d'une autre, le polymorphisme fait son travail naturellement).

Commentaire de wyden le 21/08/2011 17:33:49

Bien toutes tes questions on une simple réponse.

Le développement ce n'est pas facile, les nouveaux utilisent des libs, des systemes qui existe deja sans avoir une idé global de comment coder soit meme un mécanisme du meme type que ce qu'ils utilisent.

Ce que j'ai mis la ce n'est pas à utiliser dans un projets, c'est une manière d'ajouter des idées dans la tête des nouveaux développeurs.

Mais merci pour tes critiques, je t'assure que ca aidera les autres.

Bonne continuation.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

template [ par ifren ] salutje veux utilise une classe D utilisant une variable qui peut etre double ou string, je deirve de cette dernier deux autre class Dnum et Dstrpour Class derivée , Template ( POURQUOI ES-CE CI DIFFICILE) ??? [ par nawakator ] J'ai d&#233;j&#224; pos&#233; cette question, mais je la repose car elle est essentiel pour mon projet!J'ai cr&#233;er un template permettant de g&#23 c++ objet : information theorique [ par adidmamah ] bon voila g une class terrainje cré un objet :terrain t[2];ici j'imagine que le constructeur de la class est appeler 2 fois pour chaque case du tablea virtual template [ par Guillemouze ] Salut, je voudrais savoir si il est possible de faire des fonctions virtuelles template. voici mon cas : class Type { &nbsp;&nbsp;&nbsp; void toto(in Les types [ par emmanuel9 ] &nbsp;Bonjour &#224; tous, J'ai un objet TextBox par exemple et je voudrais savoir si il h&#233;rite de la classe Object ? (c'est un cas d'&#233;cole) wxXmlResource -- > récupérer un wxString = galère ? [ par satellite34 ] bonsoir,J'utilise la class wxXmlResource pour creer un menu dynamique de signets ftp ( pour un client );Jusque la tout va bien;Mon problem se situe qu CLASS -> DLL -> OBJECT VBA [ par fx_forum ] Maintenant que j'arrive a appeller en vba des fonctions c++ mises en dll , j'aimerai aller un grand au-dessus : ecrire une class, la mettre en dll et Template avec surcharge d'opérateurs [ par benjiiim94 ] &nbsp;&nbsp;&nbsp; Bonjour,J'essaie d&#233;s&#233;sp&#233;remment de cr&#233;er une petite classe pour me familiariser avec les templates. Non sans ma template et l'héritage [ par imad_lol ] salut.dans mon programme je déclare 2 classe X et Y.les 2 classe sont des classes templates et Y hérite de X :template &lt;class typ&gt;class X{ };//* Tableau de double [ par LouisJean ] louisjean dev cpp       salut tous le monde! Je n'arrive pas a récupère le tableau de double que j'ai remplis dans mon objet class.


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,484 sec (4)

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