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 :

Héritage en diamant et méthodes virtuelles


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut Héritage en diamant et méthodes virtuelles
    Bonjour,

    J'ai deux classes virtuelles pures :
    - Accessor qui défini un accesseur pour des données qui défini void m_open(void) = 0;
    - AccessorRW qui hérite de Accessor (virtual public) et qui défini un accesseur pour des données qui bloque l'écriture des autres accesseurs sur les données et qui doit utiliser m_open(void)

    J'ai 2 classes qui héritent de Accessor (virtual public) et qui définissent void m_open(void).
    - AccessorR : accèdent aux données en lecture seule
    - AccessorW : accèdent aux données en écriture

    Et je veux créer deux classes :
    - AccessorRWR : hérite de AccessorRW et de AccessorR ;
    - AccessorRWW : hérite de AccessorRW et de AccessorW ;

    Toutes ces classes sont templates.


    Or lorsque je veux utiliser des membres des classes parentes, je suis obligé de spécifier la classe :
    .Accessor<T>::attribut; alors qu'avec l'héritage publique je devrait théoriquement pouvoir directement faire : attribut; (sinon le compilateur m'insulte car le membre ne serait pas déclaré) serait-ce dû au fait que toutes mes classes sont template ?
    Ceci devient problématique lors de l'utilisation de m_open dans AccessorRW.
    Déjà suis-je obligé de redéfinir m_open dans AccessorRWR s'il est déjà défini dans AccessorR ?
    Dans le doute je l'ai quand même fait.

    Mais lorsque je compile le compilateur m'insulte encore :
    - si je met Accessor<T>::m_open() il dit qu'il ne trouve pas la référence de Accessor<T>::m_open().
    - si je met m_open(), il me dit :
    error: there are no arguments to ‘m_open’ that depend on a template parameter, so a declaration of ‘m_open’ must be available
    .

    Voici le code incriminé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template<class Type> //Rq : P est un typedef pour la mère : Accessor
        void AccessorRW<Type>::open(void)
        {
            P::m_parent.m_mutex.lock();
            m_open();
            P::isOpen = true;
        }
    Je récapitules donc mes questions :
    - est-il normal que je soit obligé de spécifier la classe mère contenant les attributs ( visibilité protected ) alors que j'hérite de ceux-ci ?
    - dans le cas d'un héritage par diamant, si j'implémente dans une branche une méthode virtuelle pure, est-ce que je peux appeler cette méthode dans la seconde branche ?
    - comment appeler m_open dans AccessorRW ?

    EDIT : merci à gbdivers et à LittleWhite pour leur aide sur le chat.
    Pour que ça fonctionne, il faut mettre :

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Bonjour,

    Il me manque un élément pour en être certain, mais je pense que ceci pourrait t'aider :
    http://www.comeaucomputing.com/techt.../#whythisarrow

    Il faut préciser quand on parle d'héritage et de template comment le lien est fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<class T>
    struct A {};
     
    template<class T>
    struct B : A<T> {};
     
    //Ou
     
    template<class T>
    struct B : A<int> {};
    N'ont pas les même implication au niveau de l'accessibilité (c'est la notion de "dependent base class").

    En utilisant ta solution, alors ça "fonctionne", cependant la solution du this-> en probablement une meilleur solution et ne devrait pas te conduire aux même erreurs (A<T>:: force la sélectionne de la fonction, mais ne conduit pas à une résolution dynamique de l'appel, d'où l'erreur).

    Pour ta question sur m_open, normalement non. L'idée est qu'il ne faut pas qu'il y ai d’ambiguïté sur le "final overrider".

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    (je me souvenais de ce problème, mais sans avoir de source pour l'explication, je lui ai dit que, te connaissant, tu allais nous trouver ça sans problème )

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Merci pour ces précisions, je n'ai pas tout compris mais je vais essayer de relire plusieurs fois et plus lentement^^

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Généralement, quand on en vient à parler d'héritage en diamant, la première réaction (et sans doute la plus sensée) à avoir, c'est de se dire "attention, danger, problème de conception potentiel"

    Dans le cas présent, je ne suis pas loin de penser que c'est effectivement le cas

    Mais, pour une fois changer, ce n'est pas LSP qui nous permet de nous en rendre compte.

    Non, ce qui nous permet de nous rendre compte qu'il y a un problème de conception, ce sont les règles de programmation par contrat, et, plus précisément le fait que les post conditions ne puissent pas être affaiblies dans la sous classe...

    C'est un peu le même principe (mais à l'envers) que celui qui fait qu'une liste triée ne peut pas hériter d'une liste non triée

    En gros, ici, si AccessorRWR est une classe qui permet l'accès en lecture / écriture et qu'elle hérite de AccessorR qui ne permet l'accès qu'en lecture seule, tu affaiblit les post conditions dans le sens où tu as une post condition dans AccessorR qui dira (même si tu ne le testes pas) que les données doivent être identiques après la lecture à ce qu'elles étaient avant la lecture et que cette post condition sera levée à partir du moment où AccessorRWR accepterait que les données soient modifiées après l'accès

    A partir de là, tu n'as plus que deux solutions :

    Soit, AccessorRWR hérite de AccessorRW et rajoute les fonctions manquant à l'interface pour fournir les possibilités de la lecture seule, soit AccessorRWR hérie directement de Accessor et implémente l'ensemble des services dont tu as besoin.

    En fait, il reste une troisième solution, étant donné que tu pars, de toutes manières, sur le principe d'une classe template: la création de politiques...

    L'idée serait de créer trois politiques (éventuellement template) totalement distinctes:
    • une politique "read only" qui ne fournit que les fonctions de lecture seule
    • une politique "write only" qui ne fournit que les fonctions d'écriture seule
    • une politique "read write" qui fournit aussi bien les fonctions de lecture que les fonctions d'écriture
    tu pourrais alors partir sur une classe Accessor proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <typename Type, type OpenModePolicy, typename AccessPolicy>
    class Accessor;
    que tu spécialiserais partiellement en fonction des politiques, voir des traits...
    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

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Je pourrais en effet faire un design pattern politique mais je serais toujours obligé d'avoir :
    - SafeThreadAccessor; //nécessaire du fait de quelques méthodes qui doivent prendre un & SafeThreadAccessor<Type>
    - SafeThreadAccessorRorW<Mode_access>; // remplace SafeThreadAccessorReadOnly et SafeThreadAccessorWritteOnly (Writte only est d'ailleurs mal choisit comme nom vu qu'on peut faire de la lecture et de l'écriture)
    - SafeThreadAccessorRW; //idem, nom mal choisit car pas assez explicite. Il permet de passer d'une session à une autre sans être interrompu par une session d'écriture (redéfini 2 méthodes et défini 1 méthode supplémentaires). Nécessaire du fait que certaines méthodes doivent prendre un & SafeThreadAccessorRW<Type>
    - SafeThreadAccessorRW_RorW<Mode_access>;

    Donc je ne pense pas qu'un design politique puisse m'apporter grand chose. Je pense que la priorité serait de renommer mes classes de façon plus explicite

    Je pense mettre mon code sur github assez vite, veux-tu que je mette un lien ici?
    Par contre les commentaires sont écris en anglais façon Neckara

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

Discussions similaires

  1. Héritage, type dynamique et méthode virtuelle
    Par LinuxUser dans le forum C++
    Réponses: 15
    Dernier message: 05/12/2012, 18h30
  2. méthode virtuelle pure et héritage
    Par Invité dans le forum Langage
    Réponses: 3
    Dernier message: 20/07/2009, 22h12
  3. héritage et méthodes virtuelles ?
    Par Didine981 dans le forum C++
    Réponses: 4
    Dernier message: 08/12/2007, 13h43
  4. [Héritage] Downcasting et méthodes virtuelles
    Par poukill dans le forum C++
    Réponses: 8
    Dernier message: 16/07/2007, 13h38
  5. Exceptions, héritage et méthodes virtuelles
    Par Nuwanda dans le forum C++
    Réponses: 13
    Dernier message: 23/05/2006, 12h06

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