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 :

Fonction viruelles et statique


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut Fonction viruelles et statique
    Bonjour,

    En fait j'ai une classe abstraite avec des fonctions virtuelles pures redefinies dans les classes filles. Et comme ces fonctions se devraient statiques. Seulement le compilo, ici g++-4.5, me dis que virtualite et static ne vont pas ensemble.

    Donc j'aurais aime connaître votre avis decu, si c'est une erreur de design, comment y remedier, etc.

    Merci d'avance!

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Ah oui effectivement c'est clair maintenant!

    Merci!

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 199
    Billets dans le blog
    160
    Par défaut
    Comme nous sommes sur un forum français, je me permet de traduire la réponse que l'on trouvera sur l'autre site:

    Voici un extrait de la norme du langage (ISO/IEC14882 - 2003-10-15)
    7 [Note: the virtual specifier implies membership, so a virtual function cannot be a nonmember (7.1.2) function. Nor can a virtual function be a static member, since a virtual function call relies on a specific object for determining which function to invoke. A virtual function declared in one class can be declared a
    friend in another class.]
    La traduction (sommaire):
    Le spécificateur "virtual" implique l'appartenance, donc une fonction virtuelle ne peut être une fonction non membre (7.1.2). Ainsi, une fonction virtuelle ne peut être un membre statique, car l'appel à la fonction virtuelle repose sur un objet spécifique afin de déterminer la fonction a invoqué. Une fonction virtuelle déclaré dans une classe peut être déclaré amie d'une autre classe.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,

    Citation Envoyé par victor_gasgas Voir le message
    Donc j'aurais aime connaître votre avis decu, si c'est une erreur de design, comment y remedier, etc.
    C++ a fait le choix de ne pas mélanger fonctions de classe (static) et liaisons tardives (fn virtuelles), donc ce n'est pas possible. Pourquoi as-tu eu besoin de fonctions statiques virtuelles ?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    En fait j'ai une collection de fonctions qui font partis de la même "famille", à savoir qu'elles me servent à effectuer des opérations sur les textures contenues dans la mémoire du GPU, comme l'allocation, l'upload de données, etc.

    Or il existe plusieurs types de texture : 1D, 2D, CubeMap, 2D_Array, etc.

    Donc j'ai tout regroupé dans une classe TextureOperation sous de fonctions statiques celles présentées ci-dessus puisqu'elles ne modifiaient pas l'instance et n'avait pas besoin de créer une instance. A partir de là j'ai dérivé pour chaque type; et ayant mis en virtuelle pure dans la classe de base il ne restait plus qu'à redéfinir.

    J'ai donc choisis le design suivant : Il y a une classe texture qui peut prendre comme type n'importe lequel. Ensuite en fonction de ce type j’appelais le bon TextureOperation (grâce a un std::find_if car j'ai un std::vector possédant une instance de chacun des classes dérivées).

    Il m’a donc fallut enlevé le static pour que sa compile et je pense bien avoir une erreur de design...

    Si ce n'est pas trop clair je peux poster un bout de code pour résumer un peu mieux.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Je vois à priori 2 approches :
    * Tu as une seule classe texture et elle peut alors utiliser une fabrique d'opération. Cette fabrique peut simplement s'appuyer sur un std::map<key,std/tr1/boost::function<void (void)>>.

    * Tu as une hiérarchie de classes texture et à chaque classe correspond une opération. Tu peux t'inspirer du double dispatch:
    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
    class base
    {
    public:
       virtual ~base(){}
       void operation()const
       {
          do_operation();
       }
    private:
       virtual void do_operation()const=0;
    };
     
    class A;
     
    template<class T> struct operation_policy;
    template<> struct operation_policy<A>
    {
       void do_it(A const&);
    };
     
    class A : public base
    {
    private:
       virtual void do_operation() const
       {
          operation_policy<A>().do_it(*this);
       }
    };
    ou en t'inspirant du CRTP:
    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
    template<class T> struct operation_policy;
     
    template<class Derive>
    class base
    {
    public:
       virtual ~base(){}
       void operation()const
       {
          operation_policy<Derive>().do_it(static_cast<Derive const&>(*this));
       }
    };
     
    class A : public base<A>
    {
    };
     
    template<> struct operation_policy<A>
    {
       void do_it(A const&);
    };

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Je suis plutôt dans la première approche.

    Ayant plusieurs fonctions à redéfinir à chaque fois, il me faut au tant de std::map que de fonction (j'utilise c++0x donc c'est bon pour std::function)

    Et y aurait-il un moyen de remplir ces map tout seul où je tout faire a la main comme actuellement quand je rempli mon std::vector.

    Merci pour votre intérêt!

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Si ton compilateur le permet, tu peux utiliser les initialisations à la C++11:
    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
    #include <functional>
    #include <map>
    #include <iostream>
    #include <algorithm>
     
    void function_1()
    {
        std::cout<<"1\n";
    }
     
    void function_2()
    {
        std::cout<<"2\n";
    }
     
    void function_3()
    {
        std::cout<<"3\n";
    }
     
    int main()
    {
        enum key {
            key_1,
            key_2,
            key_3
        };
        std::map<key,std::function<void(void)>> const my_map={
        {key_1, function_1}
        ,{key_2, function_2}
        ,{key_3, function_3}
        };
     
        std::for_each(my_map.begin(),my_map.end(),[](std::pair<const key,std::function<void(void)> > const&par )
        {
            par.second();
        }
        );
    }

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    La remarque de pyros m'a fait tilter que je n'avais peut être pas compris ton problème. J'ai repris ton message :
    Citation Envoyé par victor_gasgas Voir le message
    J'ai donc choisis le design suivant : Il y a une classe texture qui peut prendre comme type n'importe lequel. Ensuite en fonction de ce type j’appelais le bon TextureOperation (grâce a un std::find_if car j'ai un std::vector possédant une instance de chacun des classes dérivées).

    Il m’a donc fallut enlevé le static pour que sa compile et je pense bien avoir une erreur de design...
    A priori, ce n'était pas un si mauvaise idée que ça. Tu avais 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
    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
    #include <map>
    #include <memory>
    namespace
    {
    struct Operations
    {
       virtual void f1()=0;
       virtual void f2()=0;
       virtual void f3()=0;
    };
     
    struct Operations_1 : public Operations
    {
       virtual void f1(){}
       virtual void f2(){}
       virtual void f3(){}
    };
     
    struct Operations_2 : public Operations
    {
       virtual void f1(){}
       virtual void f2(){}
       virtual void f3(){}
    };
     
    struct Operations_3 : public Operations
    {
       virtual void f1(){}
       virtual void f2(){}
       virtual void f3(){}
    };
     
    enum Keys
    {
       Key_1
       ,Key_2
       ,Key_3
    };
    typedef std::map<Keys,std::shared_ptr<Operations>> type_operations_cont;
    }
     
     
     
    int main()
    {
       type_operations_cont operations=
       {
          {Key_1,std::shared_ptr<Operations>(new Operations_1)}
          ,{Key_2,std::shared_ptr<Operations>(new Operations_2)}
          ,{Key_3,std::shared_ptr<Operations>(new Operations_3)}
       };
     
       operations[Key_1]->f1();
       operations[Key_2]->f3();
       operations[Key_3]->f2();
     
       return 0;
    }


    Citation Envoyé par victor_gasgas Voir le message
    Si ce n'est pas trop clair je peux poster un bout de code pour résumer un peu mieux.
    vas-y. Ca clarifiera toujours un peu

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    En fait c'est exactement le code que tu as donné

    Juste peut-être quelque points :

    - J'utilise pas une std::map mais un std::vector avec std::find_if + une lambda. Mais je pense pas changé car la key est viens de la classe Opération dérivée : c'est une fonction membre redéfinie.

    - J'utilise comme toi des std::shared_ptr mais je les crées avec std::make_shared plutôt qu'un new.

    Mais bon en fait c'est le fait d'avoir du retirer le static pour compiler qui m'avait paru bizarre comme solution.

Discussions similaires

  1. [PHP 5.0] Fonction ou méthode statique
    Par grinder59 dans le forum Langage
    Réponses: 15
    Dernier message: 06/09/2012, 17h36
  2. Réponses: 10
    Dernier message: 01/04/2010, 00h34
  3. Boost thread avec fonction membre non statique.
    Par Klaim dans le forum Boost
    Réponses: 2
    Dernier message: 11/08/2007, 03h58
  4. [AS2] Pb accès fonctions statiques
    Par wwave dans le forum ActionScript 1 & ActionScript 2
    Réponses: 1
    Dernier message: 08/02/2006, 15h18
  5. [MFC] Pointeur this et fonctions statiques
    Par Yellowmat dans le forum MFC
    Réponses: 5
    Dernier message: 08/02/2005, 11h15

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