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 :

conversion entre les classes et héritage.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut conversion entre les classes et héritage.
    Bonjour

    Je ne comprends pas pourquoi il n'est pas possible de convertir un objet d'une classe dérivée secondaire en une classe de base, lorsque cette classe dérivée secondaire hérite d'une classe dérivée primaire (qui elle-même hérite directement de la classe de base).

    Je m'explique avec un exemple:
    On a une classe B qui hérite de manière privée de A, et une classe C qui hérite de manière public de B.

    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
     
    class A{
    private:
    	int o;
    public:
    	A(int u):o(u){}
    	int g(){
    		return 1;
    	}
    };
     
    class B:private A{
    private:
    	int i;
    public:
    	B(int f,int k):A(k),i(f){}
    	int f(int o){
    		this->g();
    	};
    };
     
    class C:public B{
    private:
    	int i;
    public:	 
            //ctor pas défini ici.
    	int f(int o){
    	(this)->g();
    	};
    };
    On voit qu'il n'y a pas d'erreur avec la première fonction f(), mais il y a une erreur avec la fonction f de la classe C.
    Pourtant il est parfaitement possible de convertir un objet de la classe dérivée B en un objet de la classe dérivée A bien que l'héritage soit privé.
    Il est possible de convertir un objet de la classe dérivée C en un objet de la classe dérivée B, l'héritage étant public.

    Mais il n'y a pas de transitivité? Il n'est pas possible de convertir un objet C en un objet A.

    Que pourrait faire un dynamic_cast?


    De plus, j'ai cru comprendre que l'héritage privé signifiait qu'un objet d'une classe dérivée n'était pas du tout du type de la classe de base, mais ne pouvait profiter uniquement de l'implémentation.

    Or, la conversion n'est-elle pas contradictoire avec ce qui vient d'être dit, car l'objet converti sera en quelque sorte un objet de la classe de base.




    Je vous remercie
    Pierre

  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
    Par défaut
    J'utilise peu l'héritage privé, mais il me semble que ce n'est pas vraiment à utiliser dans une hiérarchie d'héritage. Si B hérite de 1, B n'est *pas* une spécialisation de A. Ils utilisent A.

    Je trouve donc étrange que tu puisses convertir un objet de la classe B en un objet de la classe A. Car cela signifierait que des méthodes publiques devenues privées par l'héritage privé redeviendrait publiques.

  3. #3
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Je trouve donc étrange que tu puisses convertir un objet de la classe B en un objet de la classe A. Car cela signifierait que des méthodes publiques devenues privées par l'héritage privé redeviendrait publiques.
    je trouve cela étrange aussi. Mais regarde ici:

    http://msdn.microsoft.com/en-us/library/5bw4yh4d.aspx

    Conversion to a private base class type is acceptable only for pointers to immediate derived classes. Therefore, pointers of type Derived1 * can be converted to type Base *.

  4. #4
    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,

    Le fait est que l'héritage privé n'a rien d'un héritage polymorphe (ad-hoc, de surcharge ou de coercition):

    L'héritage privé n'a pas la pas la sémantique d'une relation EST-UN que peut avoir l'héritage public, mais bien la sémantique "est implémenté en terme de", et se rapproche donc bien plus d'un phénomène d'aggrégation (cf: cette entrée de la FAQ).

    En effet, il faut bien te dire que tout ce qui est public dans la classe de base passe dans la visibilité... privée de la classe qui hérite de manière privée de la classe de base.

    De ce fait, les différents éléments de la classe de base ne sont accessibles, comme tout élément déclaré avec accessibilité privée, qu'au départ... d'une des fonctions membre de la classe dérivée.

    Enfin, il faut te dire que, si tu décides d'hériter de manière privée d'une classe, c'est, très certainement parce que... tu souhaites "cacher" la relation qui existe entre la classe dérivée et la classe de base.

    Il n'y a donc, a priori, aucune raison valable de vouloir utiliser une instance de la classe dérivée en la faisant passer pour une instance de la classe de base, vu que... tu n'est même pas sensé savoir qu'il y a une relation entre les deux
    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

  5. #5
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Il n'y a donc, a priori, aucune raison valable de vouloir utiliser une instance de la classe dérivée en la faisant passer pour une instance de la classe de base, vu que... tu n'est même pas sensé savoir qu'il y a une relation entre les deux
    Ok, mais le cas donné dans la MSDN est un cas d'école qui montre que l'on peut convertir un pointeur d'un classe dérivée dans une classe de base. Et la question que je me pose est: comment est-ce possible de faire cela, (même si théoriquement, on n'a pas le droit de le faire comme tu viens de le dire).

  6. #6
    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
    Citation Envoyé par deubelte Voir le message
    Ok, mais le cas donné dans la MSDN est un cas d'école qui montre que l'on peut convertir un pointeur d'un classe dérivée dans une classe de base. Et la question que je me pose est: comment est-ce possible de faire cela, (même si théoriquement, on n'a pas le droit de le faire comme tu viens de le dire).
    Tu donnes toi même la réponse: si en théorie, on n'a pas le droit de le faire, il vaut mieux veiller à... ne pas le faire en pratique

    Maintenant, mais je ne pourrai jamais insister assez sur le fait que c'est particulièrement dangereux, le seul endroit où tu pourra envisager la conversion sera... une fonction membre dans laquelle this est un pointeur sur la classe directement dérivée.

    Autrement dit, dans une fonction membre non redéfinie, non virtuelle de la classe qui hérite de manière privée de la classe de base:

    using namespace std;
    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
    class Base
    {
        public:
            void foo()
            {
                cout <<"base::foo()";
            }
    };
    class Derivee : private Base
    {
        public:
            void bar()
            {
                Base* ptr=static_cast<Base*>(this);
                ptr->foo();
            }
            Base* toBase()
            {
                return static_cast<Base*>(this);
            }
    };
    class D2 : public Derivee
    {
        public:
            void doSomething()
            {
                bar();
            }
    };
    int main()
    {
        D2 obj;
        obj.doSomething();
        Base* ptr=obj.toBase();
        ptr->foo();
    }
    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. Héritage et relation entre les classes filles
    Par h_ayadi dans le forum JPA
    Réponses: 3
    Dernier message: 02/02/2012, 20h02
  2. Réponses: 2
    Dernier message: 13/03/2006, 17h25
  3. [PHP5][MYSQL]Préserver une connexion entre les classes
    Par Invité dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 02/02/2006, 11h51
  4. Réponses: 3
    Dernier message: 22/11/2005, 11h12
  5. Comparaison entre les classes et les fonctions
    Par Ashgenesis dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 08/09/2005, 19h09

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