IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Question technique sur les pointeurs de fonction


Sujet :

C++

  1. #1
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut Question technique sur les pointeurs de fonction
    Salut,

    J'utilise un outil qui doit faire des appels de fonctions dans mon code. A cet effet l'outil doit être initialisé en appelant une fonction "void init(void (*fct)(char *))"

    Je voudrais savoir si je suis obligé de lui donner un pointeur sur une fonction statique "static void maFonction(char* param)" ou si je peux également donner le pointeur d'une méthode publique de l'instance d'une classe non statique.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class maClasse
    {
    public :
    void maMethode(char*);
    }
     
    maClasse* instance = new maClasse();
    outil.init(instance->maMethode);

  2. #2
    Membre averti Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Points : 358
    Points
    358

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    http://cpp.developpez.com/faq/cpp/?p...onction_membre

    Si tu n'as aucune possibilité de modifier la fonction init de cet objet Outil, et bien il ne te reste plus qu'à avoi soit une fonction "globale", soit une fonction statique.
    Si tu peux modifier le code, tu as alors plusieurs possibilités différentes :
    - init prend en paramètre une classe abstraite ayant une fonction virtuelle de prototype void init(void (*fct)(char *)), et tu fais dériver maClasse de cette classe abstraite
    - utilisation de http://www.boost.org/doc/html/function.html
    - ou de http://www.boost.org/libs/bind/bind.html

    et il y en a sûrement d'autres auquelles je n'ai pas pensé sur le coup.

  4. #4
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par lemmel Voir le message
    Si tu n'as aucune possibilité de modifier la fonction init de cet objet Outil, et bien il ne te reste plus qu'à avoi soit une fonction "globale", soit une fonction statique.
    Oui hélas c'est une librairie C imposée, pas de modif de l'interface possible...

    Du coup je suis très embêté pour faire ce que je dois faire. En deux mots je vous explique, si par hasard une bonne âme avait une solution.

    En réalité, on doit passer à l'init de l'outil un gros tableau de fonctions qui sont des accesseurs sur un grand nombre de variables de mon logiciel.

    Chaque variable doit avoir sa paire d'accesseurs char* get() et set(char*) et je cherchais une solution pour éviter d'avoir à écrire un get et un set pour chacune individuellement et pouvoir réaliser des opérations groupées (par exemple connaître automatiquement le bon "get" et le bon "set" associés à une variable).

    L'idée était d'encapsuler chaque variable dans une classe qui fournit les accesseurs.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    je crois avoir déjà vu certains de tes posts ; c'est bien une histoire d'initialisation de périphérique, les paramètres étant en grand nombre ? Si c'est ça, il me semble qu'une approche plus "C" soit adapté :
    - l'utilisateur doit passer une structure correctement initialisée (i.e. tes différents paramètres), puis il appelle une fonction checkParam qui lui dira s'il a fait une erreur (ceci permettant de remplacer les contrôles effectuées par les "setters")
    - pour la modification ultérieure de paramètre, l'utilisateur devra utiliser une fonction de type : fonction(valeur, ID_PARAM);
    - évidemment, une fois l'initialisation réalisé, l'utilisateur ne peut plus accéder à la structure de config (une copie ayant été faite), et seule la fonction plus haut permet la modification de cette structure.

    Si tu désires réellement avoir une approche "objet" (je suis pas sûr que dans ton cas, il y ait quoique ce soit qui justifie une approche objet), il faut avoir une modélisation objet. Par exemple, tu peux faire quelque chose comme ça :
    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
     
     
    class VariableConfiguration
    {
      public:
      void changeValeur(void *) = 0;
      void * donneValeur(void) = 0;
    };
     
    class Offset : public VariableConfiguration
    {
      private:
        int valeur;
      public:
      void changeValeur(void *v) {if (v) valeur = *((int*)v);}
      void * donneValeur(void) {return valeur;}
    }
     
    std::vector<VariableConfiguration*> tabParam;
    mais c'est pas vraiment objet (à part la syntaxe) dans l'idée.


    P.S. : si c'est vraiment pour faire du C++, tu peux te passer d'utiliser des char *, et utiliser des string

  6. #6
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par lemmel Voir le message
    je crois avoir déjà vu certains de tes posts ; c'est bien une histoire d'initialisation de périphérique, les paramètres étant en grand nombre ? Si c'est ça, il me semble qu'une approche plus "C" soit adapté :
    - l'utilisateur doit passer une structure correctement initialisée (i.e. tes différents paramètres), puis il appelle une fonction checkParam qui lui dira s'il a fait une erreur (ceci permettant de remplacer les contrôles effectuées par les "setters")
    - pour la modification ultérieure de paramètre, l'utilisateur devra utiliser une fonction de type : fonction(valeur, ID_PARAM);
    - évidemment, une fois l'initialisation réalisé, l'utilisateur ne peut plus accéder à la structure de config (une copie ayant été faite), et seule la fonction plus haut permet la modification de cette structure.
    Non rien à voir avec l'init de périphérique... et de toute façon je n'ai pas le choix de l'interface : à l'arrivée je dois toujours fournir des tableaux de pointeurs de fonctions set(char*) et char* get() de chaque variable, La question est donc uniquement de savoir si je peux trouver une astuce pour construire efficacement ces fonctions et les associer automatiquement à la variable d'origine : par exemple si j'ai une variable "toto", je peux très bien définir setToto() et getToto() mais je ne sais pas les retrouver automatiquement à partir de "toto", je suis obligé d'établir moi même "en dur" cette correspondance.

    Si tu désires réellement avoir une approche "objet" (je suis pas sûr que dans ton cas, il y ait quoique ce soit qui justifie une approche objet), il faut avoir une modélisation objet. Par exemple, tu peux faire quelque chose comme ça :
    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
     
     
    class VariableConfiguration
    {
      public:
      void changeValeur(void *) = 0;
      void * donneValeur(void) = 0;
    };
     
    class Offset : public VariableConfiguration
    {
      private:
        int valeur;
      public:
      void changeValeur(void *v) {if (v) valeur = *((int*)v);}
      void * donneValeur(void) {return valeur;}
    }
     
    std::vector<VariableConfiguration*> tabParam;
    mais c'est pas vraiment objet (à part la syntaxe) dans l'idée.


    P.S. : si c'est vraiment pour faire du C++, tu peux te passer d'utiliser des char *, et utiliser des string
    Pas possible de faire comme ça, on vient de voir dans cette discussion que je ne peux pas donner à mon outil un pointeur de méthode de la classe Offset.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Si le prototype exigé est vraiment set(char*), alors cette bibliothèque est extrêmement mal programmée, car elle rend l'utilisation de variable globale obligatoire.

    Et tu n'as pas le choix, tu ne pourras pas utiliser des fonctions membres non-statiques pour un tel type. Uniquement des fonctions libres ou des fonctions membres statiques.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    Non rien à voir avec l'init de périphérique... et de toute façon je n'ai pas le choix de l'interface : à l'arrivée je dois toujours fournir des tableaux de pointeurs de fonctions set(char*) et char* get() de chaque variable,
    Est-ce vraiment impossible de demander une modification de la fonction ? Des fois, il vaut mieux prendre le temps de mettre à plat les choses.

    Je ne comprends pas bien la modélisation du problème :
    - le code est pensé C (à priori puisque la fonction init prend uniquement des pointeurs de fonctions de type globale)
    - il y aurait une "couche objet" puisque l'on trouve des accesseurs

    Mais bon, si tu n'as pas de marge de manoeuvre.

    Pas possible de faire comme ça, on vient de voir dans cette discussion que je ne peux pas donner à mon outil un pointeur de méthode de la classe Offset.
    Non en fait dans mon exemple tu aurais passé l'objet offset lui-même (donc c'est encore moins possible).

    Donc pour résumé, ton problème se situe en aval de la librairie (celle fournissant init), et tu te demandes comment simplifier ton code pour placer tous les accesseurs dans cet init ? [1]

    [1] si ta question est comment faire pour qu'une fonction anonymisée (fonction globale, ou statique) puisse travailler sur un objet particulier sans le recevoir en paramètre (via un paramètre de la fonction, ou via le pointeur this), ou sans recevoir une information permettant d'identifier l'objet sur lequel elle doit travailler, et bien la réponse est non :
    sans lien direct (pointeur this dans le cas d'une fonction membre, ou référence sur l'objet lui-même) ou indirecte (indice d'une case d'un tableau global, etc) vers la donnée, c'est pas possible de savoir sur qui travailler ; logique, non ?!

Discussions similaires

  1. Petites questions techniques sur les XML
    Par alex77722 dans le forum IGN API Géoportail
    Réponses: 1
    Dernier message: 03/08/2012, 18h25
  2. Considérations sur les pointeurs de fonctions
    Par deubelte dans le forum C++
    Réponses: 3
    Dernier message: 09/03/2010, 23h25
  3. Question technique sur les listes déroulantes
    Par kenny49 dans le forum Langage
    Réponses: 3
    Dernier message: 18/04/2007, 10h41
  4. Réponses: 4
    Dernier message: 16/11/2006, 02h10
  5. Question techniques sur les extents
    Par lecharcutierdelinux dans le forum Oracle
    Réponses: 16
    Dernier message: 24/08/2006, 09h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo