1 pièce(s) jointe(s)
Réflexion, templates et essai
Bonjour à tous,
Je me suis "amusé" à tenter de faire de la "réflexion" en c++, c'est à dire manipuler des objets à partir d'un ensemble d'objets... pas très clair mais bon.
Seulement, il faut manipuler les templates à tout va, je me retrouve rapidement avec un code dégelasse.
Dans mon code, il y a plusieurs problèmes.
- l'énorme répétition du code pour l'enregistrement des méthodes.
en effet, il faut une classe pour "sans paramètre", une classe pour "1 paramètre", une classe pour "2 paramètres"... et on double ça pour gérer le cas où le type de retour est void. D'où la première question comment simplifier ça ? (fichier methods.h)
- Le trop gros nombre de "reinterpret_cast<>", j'ai l'impression que ça pourri mon code, est-ce que vous voyiez un moyen de les virer?
- Le fait que les types soit intransigeants, c'est à dire que si votre méthode à un paramètre de type int et que vous envoyiez un double, ça va pas marcher, il n'y aura pas de cast implicite. C'est dû aux reinterpret_cast<>, raison de plus de les faire disparaître.
- Pour enregistrer une méthode, je dois spécifier si un paramètre est une référence ou un pointeur. Je créer donc une liste de "Policies".
J'ai vu que typeid(T).name() renvoie une chaine avec toutes ces infos (type, référence/valeur/pointeur,..). C'est portable, ça vaut le coup de faire un parseur pour gérer ça automatiquement ?
Pour donner un avant goût, voici ce que fait mon code :D (la partie intéressante est dans le main, en bas)
Code:
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
|
#include "objectregister.h"
using namespace std;
/*
Objet pour l'exemple
*/
class MyRootObject{
public :
void show(){
std::cout<<"I am the root."<<std::endl;
}
};
/*
Objet pour l'exemple
Manipule un entier
*/
class MyObject : public MyRootObject{
int t;
public:
MyObject():t(10){}
void set(int& n){
t = n;
n = 2 * n + 2; //pour tester si le passage par référence marche
}
int get(){
return t;
}
void show(){
std::cout<< "show" << " : " << t <<std::endl;
}
};
int main()
{
Object<MyRootObject> myRootObject("MyRootObject");//on déclare l'objet
myRootObject.method("show",&MyRootObject::show);//on déclare sa methode show
Object<MyObject> myObject("MyObject"); //on déclare l'objet MyObject
myObject.extends(&myRootObject); //qui dérive de MyRootObject, on doit le lui dire
myObject.method("set",&MyObject::set,arg(1,ref)); //on enregistre la méthode, le premier argument est une référence
myObject.method("get",&MyObject::get);
//myObject.method("show",&MyObject::show); //Si cette méthode n'est pas déclaré, la méthode parent sera appelée
//Si on met la méthode show de MyRootObject "virtual" alors c'est celle de
//MyObject qui sera appelée (logique).
//Si on la déclare, c'est celle-là qui sera appelée
MyObject* obj = myObject.construct();//pour l'instant ne support que la construction sans paramètre
std::cout << myObject.call<int>(obj,"get") << std::endl; //on appelle la méthode get de l'objet crée, et on affiche le retour
ParamList params; //une liste de paramètres
Policies police = myObject.getPolicies("set");//les "polices" de la méthode (pour savoir si c'est une méthode, un pointeur,..)
int val = 6;
params.add(val,police[1]); //on ajoute à la liste. police[1] où 1 est le premier paramètre voir déclaration de MyObject::set
//Note : 0 -> la valeur de retour
myObject.call(obj,"set",¶ms);//on appelle la fonction avec les paramètre
myObject.call(obj,"show");//on affiche la nouvelle valeur de obj, graçe à une fonction interne.
std::cout << val << std::endl;//on se rappelle que set modifie la valeur d'entrée, on vérifie que ça marche bien.
params.deleteAll(); //nom temporaire, permet de vider ParamList, pour une prochaine utilisation.
//Est aussi appelé dans le destructeur, donc il n'y en aurait pas besoin ici, mais c'est pour l'exemple.
return 0;
} |
Voilà, si vous pouviez me dire ce que vous pensez du code ainsi que répondre à mes questions, ça serait super :)
Voici les fichiers pour tester :