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

Langage C++ Discussion :

pointer générique de fonction d'une class


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut pointer générique de fonction d'une class
    Bonsoir a tous amis developers

    Google n'ayant put me trouver une réponse, j'appel votre savoir ce soir sur une question très particulière. Actuelement, je travail sur un système de répartition des taches entre des threads. Mais la ou je recontre des soucis, c'est que mon code devient très vite indigeste a cause de l'usage de beaucoup template pour crée des pointers vers des fonctions de class.

    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    // ------------------ UNE CLASS EN EXEMPLE
     
    class MA_CLASS
    {
    [...]
    };
     
     
    // ------------------ UN BOU DE CODE
     
    int (MA_CLASS::* maFonction) (); // notez que je suis obligé de precisé la class
    Ma question est : existe il un moyen de créer un pointer vers une fonction de class sans la spécifié ?

    Un truc dans cet esprit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int (class::* maFonction) (); // le pointeur est donc indépendant de la class
    Merci de votre lecture ainsi que de vos réponses éventuelles.

  2. #2
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonsoir,
    Je ne pense pas que ce que tu demandes soit possible.
    Un type « pointeur sur fonction » a besoin de connaître le type de tous les arguments et le type de retour pour être valide.
    Or on peut voir this comme un paramètre des fonctions membres.

    En gros, c'est un peu comme si une fonction membre était en fait déclarée comme la seconde ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    TYPE_RETOUR classe::foo(ARGUMENTS...);
    TYPE_RETOUR foo(classe *this, ARGUMENTS...);
     
    //********************//
     
    TYPE_RETOUR classe::foo(ARGUMENTS...) const;
    TYPE_RETOUR foo(classe const *this, ARGUMENTS...);
    Du coup, lors de l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    classe x;
    x.foo(...);
     
    => foo(&x, ...);

    Après, tout dépend ce qui te dérange exactement dans le type des pointeurs sur fonction.

    Le seul type de pointeur générique que je connaisse, c'est void*.
    Transtyper un pointeur vers void* est trivial, mais dans l'autre sens il peut y avoir des précautions à prendre.
    Par exemple, « le standard C99 laisse le transtypage depuis void * vers pointeur sur fonction indéfini » (d'après la page de manuel de dlsym).
    Je ne sais pas ce qu'il en est pour les standards C++.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void *src = ...;
    int (*dest)(double);
    *reinterpret_cast<void **>( &dest ) = src;

    Autrement, je ne garantis pas ça fonctionne, mis tu peux essayer quelque chose dans le genre :
    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
    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
    struct PointeurSurFonction
    {
     
        virtual
        ~PointeurSurFonction()
        {}
     
    };
     
     
    template <class T>
    class Fonction1 : public PointeurSurFonction
    {
     
      public:
        typedef TYPE_RETOUR (T::*fct_type)(ARGS...);
     
      private:
        fct_type m_fct;
     
      public:
        Fonction1(fct_type fct) : m_fct(fct)
        {}
     
        TYPE_RETOUR operator () (T& obj, ARGS... args) const
        {
            return (obj.*m_fct)(args...);
        }
     
    };
     
     
    template <class T>
    class Fonction2 : public PointeurSurFonction
    {
     
      public:
        typedef TYPE_RETOUR (T::*fct_type)(ARGS...) const;
     
      private:
        fct_type m_fct;
     
      public:
        Fonction2(fct_type fct) : m_fct(fct)
        {}
     
        TYPE_RETOUR operator () (T const& obj, ARGS... args) const
        {
            return (obj.*m_fct)(args...);
        }
     
    };
    Il te suffit après de ne manipuler que des pointeurs/références sur PointeurSurFonction.


    Ou alors tu t'inspires des adaptateurs pour fonction membre existants, si ceux-là ne te conviennent pas.
    mem_fun
    mem_fun_ref
    mem_fun1
    mem_fun1_ref

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Sinon y'a std::function et bind qui font un joli travail.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    Bonsoir,

    tout d'abord, merci beaucoup de ton temps de réponse ! Maintenant, j'ai déjà essayé avec des class semblable à celle que tu propose, mais le problème reste aussi le même étant donné que se sont des templates donc le nom de la class doit être spécifié.

    considérons deux class différente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    class CLASS_A
    {
    public:
          int fonction (float * Coords, unsigned int * Indices);
    };
     
    class CLASS_B
    {
    public:
          int fonction (char * FilePath, unsigned int * Params);
    };
    Ces deux fonctions sont d'après le C++ complètement différent au niveau de l'appel, mais pourtant, niveau assembleur, les instructions d'appel seron exactement les mêmes ... Et donc en exemple C++, le compilateur détecte une erreur juste avec un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int (CLASS_B::* maFonction) (char *, unsigned int *) = reinterpret_cast <int (CLASS_B::*) (char *, unsigned int *)> (&CLASS_A::fonction) ;
    Dès l'instant ou je peut effectuer cette opération d'une manière ou d'une autre, le problème pourrait être considéré comme résolu.

  5. #5
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    pas besoin de ces horreurs : bind et function font l'affaire :

    http://codepad.org/9ASRgY9n

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #include <boost/bind.hpp>
    #include <boost/function.hpp>
     
    class A
    {
      public :
     
      int foo( const char* c) { return 1337; }
    };
     
    class B
    {
      public :
     
      int foo( const char* c) { return 4242; }
    };
     
    int main()
    {
      A a;
      B b;
     
      boost::function<int(const char*)> pfs[2];
     
      pfs[0] = boost::bind( &A::foo, &a, _1);
      pfs[1] = boost::bind( &B::foo, &b, _1);
     
      std::cout << pfs[0]("lol") << "\n";
      std::cout << pfs[1]("lol") << "\n";
     
    }

  6. #6
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    Citation Envoyé par Joel F Voir le message
    pas besoin de ces horreurs : bind et function font l'affaire :

    http://codepad.org/9ASRgY9n

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #include <boost/bind.hpp>
    #include <boost/function.hpp>
     
    class A
    {
      public :
     
      int foo( const char* c) { return 1337; }
    };
     
    class B
    {
      public :
     
      int foo( const char* c) { return 4242; }
    };
     
    int main()
    {
      A a;
      B b;
     
      boost::function<int(const char*)> pfs[2];
     
      pfs[0] = boost::bind( &A::foo, &a, _1);
      pfs[1] = boost::bind( &B::foo, &b, _1);
     
      std::cout << pfs[0]("lol") << "\n";
      std::cout << pfs[1]("lol") << "\n";
     
    }
    d'après mes tests, un appel de fonction avec std::function c'est 3 à 4 fois plus cher qu'un foncteur classique, sans compter les couts supplémentaires des placeholders de bind

    après tout dépend de l'application évidemment

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/03/2005, 12h37
  2. Réponses: 4
    Dernier message: 10/02/2005, 16h10
  3. [VB6]Valeurs une collection renvoyée par la fonction d'une classe
    Par jacma dans le forum VB 6 et antérieur
    Réponses: 14
    Dernier message: 30/03/2004, 11h04
  4. Réponses: 4
    Dernier message: 17/03/2004, 17h24
  5. Réponses: 14
    Dernier message: 15/01/2004, 01h15

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