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 :

Inversion de control sans allocation dynamique?


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 10
    Par défaut Inversion de control sans allocation dynamique?
    Bonjour,
    Avec les nouveauté du C++11. Je me demandais si il est possible de faire de l'inversion de contrôle sans avoir à faire de l'allocation dynamique.
    Je pensais à l'utilisation de std::move et héritage mais ça ne marche pas.
    Vous avez une idée?

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,
    Ça veut dire quoi "faire de l'inversion de controle" ?

  3. #3
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 10
    Par défaut
    Hello,
    L'idée c'est d'avoir une décorrélation entre l'instanciation d'un objet et sont utilisation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class IAnimal
    {
    	public:
    	virtual void Mange() = 0;
    };
    void Programme()
    {
    	IAnimal iAnimal = GetAnimal(...);
    	animal.Mange();
    }
    On pourrait utiliser l'allocation dynamique mais je me dis que pour des objets qui nécessitent peu de mémoire ce serait beaucoup moins intéressant d'utiliser la heap.

  4. #4
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    selon ton exemple, cela s'appelle juste du polymorphisme... Pour réaliser une résolution dynamique des liens tu n'as pas d'autre choix d'utiliser un pointeur ou une référence.

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Non, l'inversion de contrôle ne se réduit pas au polymorphisme, elle consiste à décharger le code client utilisateur d'une hiérarchie de la responsabilité de choisir ce qui est instancié. La cas idéal est de ne donner au code client que la connaissance d'un interface (donc en c++ une classe abstraite ne contenant que des fonctions virtuelles pures). Un code dédié se charge de retourner des instances de classes d'implémentation adaptées au cas (par exemple à la configuration, ou en fonction du chargement de plugins).
    La notion d'inversion de contrôle est donc plus liée à la notion de factory.
    A priori, l'inversion de contrôle ne nécessite pas en soi l'allocation dynamique, puisqu'on peut renvoyer un pointeur ou une référence à partir d'un objet membre à condition de ne pas faire de c*** avec les durées de vie...
    Après, si tu cherches à configurer tes factories en fonction de paramètres runtime, ça devient plus difficile d'éviter l'allocation dynamique, mais ce n'est pas forcément infaisable.

  6. #6
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par therwald Voir le message
    La notion d'inversion de contrôle est donc plus liée à la notion de factory.
    Un mix de Strategy et Factory pattern, pour etre precis.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,
    Citation Envoyé par therwald Voir le message
    Non, l'inversion de contrôle ne se réduit pas au polymorphisme, elle consiste à décharger le code client utilisateur d'une hiérarchie de la responsabilité de choisir ce qui est instancié. La cas idéal est de ne donner au code client que la connaissance d'un interface (donc en c++ une classe abstraite ne contenant que des fonctions virtuelles pures). Un code dédié se charge de retourner des instances de classes d'implémentation adaptées au cas (par exemple à la configuration, ou en fonction du chargement de plugins).
    La notion d'inversion de contrôle est donc plus liée à la notion de factory.
    A priori, l'inversion de contrôle ne nécessite pas en soi l'allocation dynamique, puisqu'on peut renvoyer un pointeur ou une référence à partir d'un objet membre à condition de ne pas faire de c*** avec les durées de vie...
    Après, si tu cherches à configurer tes factories en fonction de paramètres runtime, ça devient plus difficile d'éviter l'allocation dynamique, mais ce n'est pas forcément infaisable.
    Il n'y a rien à faire:

    Une grande partie de l'inversion de contrôle passe par le polymorphisme: le fait qu'un comportement qui est disponible au niveau de la classe de base puisse être adapté au type réel de l'objet manipulé, qui correspond à un type dérivé de la classe de base.

    Le fait est que tu ne peux profiter du polymorphisme, en C++, qu'au travers de pointeurs ou de références!

    Tu pourrais donc avoir un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class IAnimal
    {
    	public:
    	virtual void Mange() = 0;
    };
    void Programme()
    {
    	IAnimal /* const */ & iAnimal = GetAnimal(...);
     
    	animal.Mange();
    }
    pour autant que GetAnimal renvoie une référence (éventuellement constante) sur une instance particulière de IAnimal.

    Le problème vient alors de la durée de vie des variables (non statiques) pour lesquelles on n'a pas eu recours à l'allocation dynamique de la mémoire d'une part et à la sémantique d'entité qui est associée aux classes qui interviennent dans une hiérarchie d'objet d'autre part.

    En effet, les variables non statiques pour lesquelles on n'a pas recours à l'allocation dynamique sont automatiquement détruites lorsque l'on atteint l'accolade fermante '}' de la portée dans laquelle les variables sont déclarées.

    Si tu as une classe Chien héritant de IAnimal sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    clas Chien : public IAnimal{
        public:
            /* ... */
    };
    un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    IAnimal & GetAnimal(/* ... */){
         Chien c(/*... */ );
         return c;
    } // c est détruit ici
    te claquera systématiquement dans les pattes parce que la référence renvoyée fera référence à... un objet qui a été détruit.
    On pourrait envisager de créer une instance statique de chien, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    IAnimal & GetAnimal(/* ... */){
         static Chien c(/*... */ );
         return c;
    }
    mais, à chaque fois que tu ne pourrais alors avoir qu'un et un seul chien.

    L'alternative est alors de créer un type contenant un tableau de chiens et de veiller à placer l'objet à chaque fois dans le tableau, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class AnimalFactory{
        public:
            IAnimal& getAnimal(/* ...*/){
                 if(/* c'est un chien */ ){
                     return createChien(/* ... */);
                 }
            }
        private:
            IAnimal & createChien(/*... */){
                chiens_.push_back(Chien(/* ... */ );
                return chiens_[chiens_.size()-1];
            }
            std::vector<Chien> chiens_;
    };
    parce qu'il n'est pas possible de créer une collection de références.

    Tu serais donc obligé de maintenir une collection pour chaque type d'animal spécifique, et tu serait malgré tout limité, pour la durée de validité de ta référence, à la durée de vie de la factory sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(){
        if(une condition){
            AnimalFactory factory;
            IAnimal & animal = factory.GetAnimal(/* ... */);
        } // factory est détruit ici. La référence animal est invalidée à cause de ca
        return 0;
    }
    Mais, de plus, ce code se heurte de plein fouet à la sémantique d'entité associée aux classes qui interviennent dans une hiérarchie de classes!

    En effet, une classe ayant sémantique d'entité n'est, par nature, ni copiable ni assignable.

    Cela signifie que ta classe IAnimal devrait prendre la forme de (C++11 inside )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class IAnimal
    {
    	public:
            IAnimal(IAnimal const &)  = delete;
            IAnimal& operator = (IAnimal const &) = delete;
    	virtual void Mange() = 0;
    };
    et que toutes les classes qui héritent (de manière directe ou indirecte) de IAnimal seront elles aussi non copiable et non assignable.

    Sans recourir à la sémantique de mouvement, il te sera impossible de rajouter ton chien dans la collection de chien, parce qu'il n'est pas copiable.

    Et le fait d'utiliser un tableau "C style" comme collection ne changera rien: un chien n'est pas assignable

    Tu te retrouves donc "obligé", si tu veux disposer de différents animaux en les connaissant comme des IAnimal, de gérer leur durée de vie sous la forme de pointeurs, et donc de recourir à l'allocation dynamique.

    Ceci dit, C++11 dispose maintenant de classes de pointeurs RAIIsantes, et il serait sans doute intéressant d'envisager d'utiliser un std::unique_ptr<Chien> (ou std::unique_ptr<IAnimal>, selon ce qui t'intéresse le plus) dans la collection qui maintient les différentes instances de chiens (ou d'animaux)

    L'idée est alors d'utiliser le pointeur nu (IAnimal * ) renvoyé par la fonction get de unique_ptr chaque fois que tu a "juste" besoin de pouvoir disposer de l'objet, et de te dire que tu n'as pas besoin de t'inquiéter de la durée de vie de l'objet sous-jacent
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 14/11/2009, 15h49
  2. petit pbm allocation dynamique de stringGrid
    Par AnneOlga dans le forum C++Builder
    Réponses: 10
    Dernier message: 17/01/2004, 11h59
  3. Allocation dynamique de structures
    Par fr_knoxville dans le forum C
    Réponses: 8
    Dernier message: 06/05/2003, 21h59
  4. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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