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 :

Casse-tête entre polymorphisme d'héritage et classes génériques


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juillet 2005
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 51
    Points : 38
    Points
    38
    Par défaut Casse-tête entre polymorphisme d'héritage et classes génériques
    Bonjour a tous,

    merci à ceux qui liront et essayerons de m'aider.

    Je me confronte a un probleme bien tordu qui releve surement d'un probleme de Design de mon code mais je trouve aucune solution valable la.

    Voici le code (simplifié car je ne peux pas copier le code original qui est privé):

    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
     
    class Addition: public IOperation
    {
    public:
     
    	virtual ~Addition(){}
     
    	//void DoOperation(Value a, Value b) const = 0;
     
    };
     
    //! Typedef
    typedef boost::shared_ptr<const Addition> AdditionConstPtr;
     
     
    /*!
           Templated Implementation
    */
    template<typename Value>
    class AdditionValue: public Addition, public OperationValue<Value>
    {
    public:
          AdditionValue();
     
          void DoOperation(Value a, Value b);
     
    protected:
     
          //! Typedef
          typedef boost::shared_ptr<const AdditionValue<Value> > AdditionValueConstPtr;
     
    private:
            Value m_AdditionResult;
    }
    Donc, on a une classe abstraite mere Addition et la classe AdditionValue qui permet de templétisé l'opération Addition suivant le type des données.

    Ensuite dans le code on a une autre classe qui a un membre de type AdditionValue templétisée aussi:

    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
     
    template <typename Value>
    class CheckOperationValue: public CheckOperation
    {
     
         //! Typedef
         typedef boost::shared_ptr<const AdditionValue<Value> > AdditionValueConstPtr;
     
     
        //! Accessors
        AdditionConstPtr getAddition() const final;
     
    private:
        mutable AdditionConstPtr m_AdditionCPtr;
    }
     
    template<typename Value>
    AdditionConstPtr CheckOperationValue<Value>::getAddition() const
    {
        if (! m_AdditionCPtr)
        {
            build_addition();
        }
     
        return m_AdditionCPtr;
    }
     
    template<typename Value>
    void CheckOperationValue<Value>::build_addition() const
    {
        // build Addition operator
        m_AdditionCPtr = AdditionValueConstPtr(boost::make_shared<AdditionValue<Value> >()));
    }
    et donc mon problème vient au moment ou dans mon code j'ai instancié un CheckOperation et je veux faire la chose suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    double a, b;
     
    ...
     
    auto checkOPCPtr = ...;
    auto addOPCPtr = checkOPCPtr->getAddition();
    addOPCPtr->DoOperation(a,b)
    En effet, on a un pointeur sur la classe de base Addition (non templétisé) qui utilise une fonction membre de la classe templétisé AdditionValue, et donc je ne peux pas définir cette fonction dans la classe de base car pas de template. Si je crée la classe de base comme template, j'ai ensuite un autre problème du meme genre.

    C'est assez compliqué et j'espere que mon exemple qui n'a aucun sens reprend bien le probleme dans mon contexte.

    Merci de vos conseils en avance !!!

  2. #2
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Il faut que tu passes par une classe qui encapsule la donnée, pas trop le choix autrement, héritage + template ça ne fonctionne pas des masses.

    J'avais fait un truc dans ce gout là à l'époque:
    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
    class Variant
    {
    public:
    	template<typename T>
    	void set(T data) {
    		m_size = sizeof(data); m_data = new char[sizeof(data)]; memcpy(m_data, &data, sizeof(data));
    	}
    	template<typename T>
    	void get(T& ret) { if (sizeof(ret) == m_size) memcpy(&ret, m_data, sizeof(ret)); }
    	void* m_data = nullptr;
    	size_t m_size = 0;
    };
     
    class Mere
    {
    public:
    	Mere() {}
    	template<typename T>
    	T doOperation(T a, T b) { Variant v1, v2, result; v1.set(a); v2.set(b); doOperation(v1, v2, result); T res; result.get(res); return res;}
    private:
    	virtual void doOperation(Variant& a, Variant& b, Variant& result) = 0;
    };
     
    template<typename T>
    class Fille : public Mere
    {
    public:
    	Fille() {}
    private:
    	virtual void doOperation(Variant& a, Variant& b, Variant& result) override 
    	{
    		T v1;
    		T v2;
    		a.get(v1);
    		b.get(v2);
    		result.set(v1+v2); 
    	};
    };
    à toi de reprendre pour pouvoir l'adapter et ajouter les cas d'erreur aussi pour pas que ça parte en vrille. Avec les nouveauté de c++, je crois que tu peux aussi stocker le typeId pour être sur que les données sont du même type (car le sizeof permet juste d'éviter le crash et non la transformation de donnée).
    Pas de solution, pas de probleme

    Une réponse utile (ou +1) ->
    Une réponse inutile ou pas d'accord -> et expliquer pourquoi
    Une réponse à votre question


  3. #3
    Nouveau membre du Club
    Inscrit en
    Juillet 2005
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 51
    Points : 38
    Points
    38
    Par défaut
    Merci pour ta réponse, je dois y réfléchir un peu, car dans mon cas je suis obligé d'utiliser un template car mon code est intégré avec une librairie de différentiation automatique (FADBAD) et donc pour pouvoir utiliser les fonctionnalités, il faut que le type soit générique.

    Donc je suis pas sur de pouvoir créé mon propre type générique, en tout cas c'est une bonne idée merci.

    D'un autre coté, j'ai vu des gens faire des dynamic_cast pour forcer à etre avec l'objet templatisé, mais ça résout pas tous les problèmes je pense.

    Je reste ouvert à d'autres idées ...

  4. #4
    Nouveau membre du Club
    Inscrit en
    Juillet 2005
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 51
    Points : 38
    Points
    38
    Par défaut
    Bon, apparemment la solution était pas si compliquée que ça, il fallait déclaré ma fonction comme template dans la classe de base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<typename Value>
    void DoOperation(Value a, Value b) const{ Raise Exception("Method not implemented here");}

  5. #5
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Sauf que si tu fais ça, tu ne pourras pas la réimplémenter dans les classes filles (virtual + template c'est pas possible)
    Pas de solution, pas de probleme

    Une réponse utile (ou +1) ->
    Une réponse inutile ou pas d'accord -> et expliquer pourquoi
    Une réponse à votre question


  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je comprends que Addition soit une IOperation, mais en quoi AdditionValue devrait être une Addition ?
    La hiérarchie en place me semble mauvaise.
    Et le code bien trop court pour comprendre le vrai problème et donc espérer une solution.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Juillet 2005
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 51
    Points : 38
    Points
    38
    Par défaut
    Citation Envoyé par skeud Voir le message
    Sauf que si tu fais ça, tu ne pourras pas la réimplémenter dans les classes filles (virtual + template c'est pas possible)
    Rebonjour, pour cloturer le sujet et surtout donner une solution qui pourrait etre utile a d'autres, effectivement il y avait encore un probleme avec ma solution et il a fallu adapter de cette maniere:


    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
     
    template<typename Value>
    void DoOperation(Value a, Value b) const;
     
    /*
        Implementation Addition
    */
     
    template <typename Value>
    void Addition::DoOperation(Value a, Value b) const
    {
        const AdditionValue<Value>* AdditionCPtr = dynamic_cast<const AdditionValue<Value>*>(this);
        SQ_REQUIRE(AdditionCPtr, "bad type");
        return AdditionCPtr->DoOperation(a, b);
    }
    Donc comme vous pouvez le voir, une maniere de remédier au probleme d'incompatibilité entre virtual et template dont parlait skeud c'est de ne pas déclarer virtuel la fonction dans la classe Operation, mais la définir en forçant le cast et donc l'appel a la fonction de la classe Fille AdditionValue.

    On peut clore le sujet avec cette solution?

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

Discussions similaires

  1. Conception d'une classe : casse-tête
    Par Tomaka17 dans le forum C++
    Réponses: 9
    Dernier message: 22/03/2009, 17h09
  2. Réponses: 6
    Dernier message: 17/12/2007, 16h16
  3. Casse tête sur du friend avec de l'héritage
    Par Drannor dans le forum C++
    Réponses: 4
    Dernier message: 03/10/2007, 22h20
  4. casse-tête sur les adresses (classe C et A)
    Par HuZimA dans le forum Protocoles
    Réponses: 7
    Dernier message: 27/07/2006, 13h05
  5. Classe, pile, pointeurs et casse-tête!
    Par zazaraignée dans le forum Langage
    Réponses: 6
    Dernier message: 26/09/2005, 16h57

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