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 :

Classes virtuelles et méthodes d'accès aux données privées


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut Classes virtuelles et méthodes d'accès aux données privées
    Bonjour à tous,

    Je dispose d'une classe DA qui contient un constructeur et un destructeur, ainsi que des data en protected :

    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 DA
    {
    public:
      DA();
      DA(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~DA();
     
    private:
    protected:
      char * DataAttributeName;
      char * FunctionalConstraint;
      char * TrgOp;
      char * M_O_C;
    };
    Ensuite, je dispose d'autres classes (une par type de données en fait) qui récupèrent les data protégées de la classe mère et qui en implémentent une nouvelle pour chacune:
    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
     
    class BOOLEAN_TYPE : public DA
    {
    public:
      BOOLEAN_TYPE();
      BOOLEAN_TYPE(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~BOOLEAN_TYPE();
     
    private:
      bool Value;
     
    protected:
    };
     
    class ET_IEC_DIRECTIONAL_TYPE : public DA
    {
    public:
      ET_IEC_DIRECTIONAL_TYPE();
      ET_IEC_DIRECTIONAL_TYPE(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~ET_IEC_DIRECTIONAL_TYPE();
     
    private:
      ET_IEC_DIRECTIONAL Value;
    protected:
    };
     
    /* Beaucoup d'autres ... */
    Mon objectif est de créer à partir de là des fonctions qui permettent d'accéder aux données "Value" de chaque classe fille. L'idéal aurait-été de créer une seule fonction en public dans la classe mère et que toutes les classes filles puissent l'utiliser par héritage. Le problème est que le type de "Value" diffère pour chaque classe fille. Je cherche une solution qui me permette d'éviter de coder une fonction pour chaque type de "Value".

    Quelqu'un connaitrait-il une méthode efficace ?

  2. #2
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    ce problème est typiquement le genre de choses que l'on résous avec des templates, je te conseille donc de te chercher de ce côté. Ensuite, les détails d'implémentation dépendront des spécificités de ton programme.

    Cordialement.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut
    Merci pour la réponse, effectivement j'étais passé à côté des templates. Je suis en train de voir comment utiliser cet outil de façon optimale, sachant que je suis confronté à plusieurs problèmes:

    - La première solution serait de définir la classe DA en template. Par contre, l'architecture de mon code est la suivante: Une classe "server" dispose de private data de type "class LD" qui elle même dispose de privata data de type "class LN", ... qui contient des private data de type "class DA". Ainsi, si je déclare DA en template, cela implique que le niveau supérieur soit aussi déclaré en template, puis encore le niveau supérieur, ...

    - La deuxième solution serait d'utiliser une fonction déclarée en template dans la classe DA. La fonction serait qqch comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public:
    template<typename T>
    T GetVal()
    {
      return Value;
    }
    private:
    T Value;
    Bien entendu, le compilateur hurle car il ne connait pas le type T lors de la déclaration de Value. Quelle serait la solution pour corriger ce problème ?

    Julien.

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par Khan34 Voir le message
    - La première solution serait de définir la classe DA en template. Par contre, l'architecture de mon code est la suivante: Une classe "server" dispose de private data de type "class LD" qui elle même dispose de privata data de type "class LN", ... qui contient des private data de type "class DA". Ainsi, si je déclare DA en template, cela implique que le niveau supérieur soit aussi déclaré en template, puis encore le niveau supérieur, ...
    Pas si tu définis un pointeur vers nue classe parente qui ne dépend pas de ce type variable. Mais il ne faut que tu aies besoin d'accéder à cette donnée à partir de ce pointeur...

    Pour ta seconde solution, je en comprend pas bien le problème.
    [EDIT BY KOALA01]supprimé car modification effectuée par moi[/EDIT]

    Merci également, dans ton second post, de mettre ton code dans entre balises de code...

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut
    J'ai corrigé les remarques concernant le deuxième post; par contre je n'ai pas pu pour le premier post, je ne peux pas l'éditer (il semblerait qu'il ait été édité par un administrateur préalablement).

    La 2nde solution dont je parlais dans le post précédent permettais d'éviter de créer un template classe et de seulement créer un template fonction qui serait par la suite utilisé dans la classe. Le problème est que la fonction doit renvoyer la donnée défini en private dans chaque classe fille de DA, mais pas dans la classe DA elle même. Donc naturellement le compilateur me dit que la valeur que j'essaye de renvoyer n'est pas définie. J'ai donc définie une variable symbolique dans DA (T value) mais bien entendu, le compilateur me dit qu'il ne connait pas le type T.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Dans ta classe fille, fais un typedef.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class A { ... };
     
    class B : A
    {
        typedef int titi;
     
        int var;
     
        int getVar() { return var; }
    }
     
    B monInstance;
    B::titi toto = monInstance.getVar();

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut
    Je ne peux pas accéder à l'objet B sans passer au préalable par les objets de niveaux supérieurs. J'ai bricolé un peu et voila ce que ça donne:

    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
    union DATATYPE
    {
      bool BT;
      ET_IEC_DIRECTIONAL ET;
      QUALITY QT;
      TIMESTAMP TT;
    };
     
    class DA
    {
    public:
      DA();
      DA(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~DA();
     
      virtual DATATYPE GetVal() = 0;
     
    private:
     
    protected:
      char * DataAttributeName;
      char * FunctionalConstraint;
      char * TrgOp;
      char * M_O_C;
    };
     
    class BOOLEAN_TYPE : public DA
    {
    public:
      BOOLEAN_TYPE();
      BOOLEAN_TYPE(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~BOOLEAN_TYPE();
     
      DATATYPE GetVal();
     
    private:
      bool Value;
     
    protected:
    };
     
    class ET_IEC_DIRECTIONAL_TYPE : public DA
    {
    public:
      ET_IEC_DIRECTIONAL_TYPE();
      ET_IEC_DIRECTIONAL_TYPE(char * Name, char * FC, char * TrgOp, char * M_O_C);
      ~ET_IEC_DIRECTIONAL_TYPE();
     
      DATATYPE GetVal();
     
    private:
      ET_IEC_DIRECTIONAL Value;
    protected:
    };
    La déclaration de l'union DATATYPE me permet de créer une seule et unique fonction virtuelle dans la classe mère (au lieu d'une pour chaque type).
    Ensuite, la fonction GetVal() donne pour le BOOLEAN_TYPE:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    DATATYPE BOOLEAN_TYPE::GetVal()
    {
      DATATYPE tmp;
      tmp.BT = Value;
      return tmp;
    }
    Puis dans mon main, l'accès aux données est fait de la façon suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Server * ServerNode = new Server();
      ServerNode->AddLD("LD1");
      ServerNode->GetLD("LD1")->AddLN("PTOC1","Ref1","PTOC");
      bool testBool = ServerNode->GetLD("LD1")->GetLN(0)->GetDO(0)->GetCDC()->GetDA(0)->GetVal().BT;
      printf("testBool = %d\n",testBool);
    Qu'en pensez-vous ? Cela fonctionne mais j'aurais espéré faire qqch de plus propre.

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut
    La chose qui est dérangeante est le fait qu'avec la méthode de l'union, j'alloue plus de mémoire que nécessaire. Par exemple, pour le cas du BOOLEAN_TYPE, je n'utilise que le bool défini dans l'union, alors que la mémoire réservée est de la taille du plus grand type de l'union.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    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 113
    Points : 32 951
    Points
    32 951
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    Ca ressemble beaucoup trop à des templates pour ne pas l'implémenter avec des templates^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template< class T >
    class DA
    {
     public:
     void SetValue(T _value) { m_kValue = _value; }
     T GetValue() const { return m_kValue; }
     protected:
     T m_kValue;
    };
    Et pour l'utilisation, il te suffit de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DA<bool> my_bool;
    DA<int> my_int;
    C'est du code rapide, pas forcément correct mais l'idée est là et ne me semble pas farfelue
    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.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 65
    Points : 38
    Points
    38
    Par défaut
    Effectivement, cela parait faisable. Après le problème qui se pose vient de la classe qui crée les objets DA:

    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 CDC
    {
    public:
      CDC();
      ~CDC();
      virtual DA * GetDA(int indice) = 0;
      /*virtual SUBDO * GetSUBDO(int indice) = 0;*/
     
    private:
    protected:
      char CDC_ID[3];
    };
     
    class ACT : public CDC
    {
    public:
      ACT();
      ~ACT();
      DA * GetDA(int indice);
     
      /* Services */
     
    private:
      std::vector<DA*> DAlist;
     
    protected:
    };
    Si j'utilise ta méthode, cela implique que les données privées de la class ACT, à savoir DAlist, ne peut plus être implémentée de cette manière. A la limite, je peux modifier les données privées et les déclarer de la façon suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private:
    DA<bool> * general;
    DA<int> * directional;
    /* ... */
    Sauf que cela implique de modifier les fonctions qui accèdent à ces données membres, et m'oblige à créer une fonction par type (si je ne me trompe pas) comme ci-dessous:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public:
    DA<bool> * GetDA(int indice);
    DA<int> * GetDA(int indice);
    /* ... */
    Qu'en penses-tu ? Sachant que la class CDC est elle même instanciée de la même manière par une autre classe, et ce sur plusieurs niveaux.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    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 113
    Points : 32 951
    Points
    32 951
    Billets dans le blog
    4
    Par défaut
    Effectivement pour une collection hétérogène de DA je ne sais pas.
    Gérer plusieurs listes de types, c'est dommage mais je ne vois pas autre chose pour l'instant, si tenté qu'il y ait autre chose.

    Mais pour créer un objet DA, il suffit de templater la fonction de création

    Sinon, tu n'utilises qu'un DA<char*> (pas forcément template du coup) et tu utilises plusieurs fonctions ToBool, ToInt, ToChar, ... (GetValue template en fait)
    C'est ce que j'ai cru voir dans des parseurs xml (tinyxml)
    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.

  12. #12
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    si la liste ne comporte pas trop de types différents, il est possible de passer par une liste de type.

    Cordialement.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

Discussions similaires

  1. Réponses: 225
    Dernier message: 26/04/2018, 18h38
  2. [PHP 5.4] méthode d'acces aux données importées d'un CSV
    Par wimbish dans le forum Langage
    Réponses: 0
    Dernier message: 16/10/2014, 17h08
  3. mvvm ria services, quelle méthode d'accès aux données
    Par Golzinne dans le forum Silverlight
    Réponses: 4
    Dernier message: 01/06/2011, 12h14
  4. Quelle méthode d'accès aux données choisir ?
    Par alex_noox dans le forum Framework .NET
    Réponses: 1
    Dernier message: 10/04/2009, 16h48
  5. [Debutant] Classe d'acces aux données
    Par Keldrhyn dans le forum Access
    Réponses: 4
    Dernier message: 18/02/2007, 21h30

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