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 de type réciproque.


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut Conversion de type réciproque.
    Une classe B qui dérive(partiellement) d'une classe A.

    Comment organiser la conversion de type B->A et la conversion de type A->B?

    La conversion du type B->A a été obtenue de manière classique par opérateur cast mais l'autre sens, A->B, malgré une déclaration anticipée, ça heurte.

    Pour l'instant une surdéfinition de l'opérateur d'affectation fait le joint mais c'est pas propre.

    Comme à l'évidence, j'ai manqué un barreau de l'échelle dans l'histoire...

  2. #2
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Points : 2 757
    Points
    2 757
    Par défaut
    salut,
    pour les pointeurs
    par exemple B hérite de A et dispose de la fonction membre FuncB()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A * ptr1 = new B();
    static_cast<B*>(ptr1)->FuncB();
    sans pointeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    A a;
    B b; // B dérive de A
     
    a = b; // OK
    b = a; // KO

  3. #3
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Oui. Tu as manqué que l'on ne transforme pas entre les divers niveaux d'une hiérarchie. Et certainement pas en surchargeant l'opérateur d'affectation vu qu'il extrêmement rare qu'une sémantique de valeur s'applique sur une hiérarchie. Plus tous les problèmes de slicing dûs à l'utilisation de sémantique de valeur dans une hiérarchie.
    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
    struct Mere {} ;
    struct Fille1 : Mere {};
    struct Fille2 : Mere {};
     
    ...
    Fille1 * f = new Fille1(42);
    // pointeur car sémantique de référence et non de valeur 
     
    // Upcasting implicite
    Mere * m = f;
     
    // Downcating, rarement bienvenu hors quelques cas bien connus,
    // que l'on explicite
    Fille1 * f2 = dynamic_cast<Fille1*>(m);
    assert(f2);
     
    Fille2 * f3 = dynamic_cast<Fille2*>(m);
    assert( ! f3);

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Le transtypage consiste à interpréter différemment une valeur, pas à la copier dans un objet d'un autre type. Sinon, effectivement, il faut implanter un constructeur par copie ou (et) inplanter l'opérateur d'affectation
    Le problème est bizarre. D'ordinaire, on a un pointeur sur une classe de base A alors que l'objet pointé est en réalité de type B. Pour transtyper le pointeur p de A* en B* :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    B* pb = dynamic_cast<B*>(p);
    if(pb) 
      {
       pb->... // permet d'accéder aux éléments de B
     }
    Je ne sais pas si je réponds vraiment à la question posée

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut
    Citation Envoyé par Luc Hermitte
    Oui. Tu as manqué que l'on ne transforme pas entre les divers niveaux d'une hiérarchie. Et certainement pas en surchargeant l'opérateur d'affectation vu qu'il extrêmement rare qu'une sémantique de valeur s'applique sur une hiérarchie. Plus tous les problèmes de slicing dûs à l'utilisation de sémantique de valeur dans une hiérarchie.
    Est-ce valable dans le cas d'une classe avec une autre classe comme objet membre?

    En fait, ma dérivation m'apparait comme une erreur de programmation puisque un objet de la classe fille peut ne pas être un objet de la classe mère(Objets totalement disjoints).

    Cependant, un objet contenant une classe membre peut aussi devenir un simple objet de cette classe membre.

    Il me faut donc assurer une correspondance commode entre les objets des différentes classes.

  6. #6
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    En fait, ma dérivation m'apparait comme une erreur de programmation puisque un objet de la classe fille peut ne pas être un objet de la classe mère(Objets totalement disjoints).

    Cependant, un objet contenant une classe membre peut aussi devenir un simple objet de cette classe membre.
    Tu devrais plutôt présenter un peu la déclaration de tes classes car pour mon compte je n'ai rien compris à tes explications

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut
    Schématiquement:
    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
     
    class A;
     
    class B{
            A bA;
    autres données membres;
     
    }
     
    class C{
            A cA;
            B cB;
    autres données membres;
     
    }
    Un objet de classe B peut être disjoint de A mais aussi recouvrir totalement A d'où besoin de conversion totale de type A->B et B->A.

  8. #8
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class A; 
     
    class B{ 
            A bA; 
    autres données membres; 
     
    }
    Il n'y a pas là la moindre trace de classe dérivée!
    Une classe A est membre de B. Elles est accessible par objB.bA .
    Un objet de classe B peut être disjoint de A mais aussi recouvrir totalement A d'où besoin de conversion totale de type A->B et B->A.
    Je ne comprends pas cette phrase.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut
    J'ai parlé d'une erreur de programmation car je pense me souvenir qu'un objet dérivé est au minimum un objet de la classe de base.

    Pour faire une analogie,

    A pourrait représenter tous les entiers pairs.
    class A{
    int p;//p=2*i par constructeur
    }
    B représente tous les entiers, pairs plus impairs.
    class B{
    A bA;
    int im//2*i+1 par constructeur
    }
    B peut être initialisé à un ensemble d'entiers impairs et donc ne représente pas un objet de A.

    Maintenant si on translate tous ces éléments de B de un, ils deviennent tous pairs et correspondent tous à la classe A: mon objet issu de la classe B est maintenant un objet se référant totalement à A.
    D'où la nécessité d'assurer une conversion de type.

    Ce n'est qu'une analogie puisqu'ici B ne peut être totalement disjoint de A, B contiendra au minimum l'objet 0 et on peut aussi dériver les impairs des pairs.

    Mais le besoin de conversion de type provient de là.

  10. #10
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Points : 2 757
    Points
    2 757
    Par défaut
    les classes telles que tu les décris n'ont strictement rien à voir avec l'héritage. c'est de la composition (ou agrégation ? je confond toujours ).

    si tu as un constructeur de B qui prend un paramètre de type A, alors tu peux écrire :
    qui est interprété comme
    et si tu veux faire l'inverse, i.e. affecté une valeur à un A à partir d'un B, il faut un opérateur de cast

    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
    class A
    {
    public:
       A();
       friend B::operator A();
    };
     
    class B
    {
    private:
       A m_a;
    public:
       B();
       B(A a);
       operator A();
    };
     
    B::operator A()
    {
       return m_a;
    }
    avec ça tu peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    A a1,a2;
    B b1(a1),b2;
     
    a2 = b1; // a2 = (A)b1;
    b2 = a2; // b2 = B(a2);
    sinon, ce que tu nous explique là est assez strange. quelle est la finalité ?

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut
    C'est exactement ce que je n'arrive pas à faire.

    J'ai en effet tenté de résoudre le problème par le même procédé.
    J'ai cependant rajouté une déclaration anticipée de la classe B.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class B;
    class A 
    { 
    public: 
       A(); 
       friend B::operator A(); 
    };
    pour essayer de contourner le fait qu'il n'y a pas connaissance de la classe B au moment de la déclaration d'amitié.
    Ca ne résout pas le problème et donne error: member 'B::operator A()' declared as friend before type B is defined.

    Je vais voir les solutions de typage dynamique qui m'ont été proposées.

    La finalité est d'évaluer s'il y a perte d'information lorsqu'on agit de la sorte. Donc un, implémenter une totale correspondance entre objets de telles classes, deux, évaluer s'il ya une perte d'information et si oui, d'où provient elle, à l'exclusion des arrondis machines.
    C'est un projet dit de détente.

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Je n'ai pas suivi tout le topic, mais pour réaliser des conversions on préfèrera souvent utiliser les constructeurs et non les opérateurs de cast.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class B;
     
    class A
    {
        A(const B& b);
    };
     
    class B
    {
        B(const A& a);
    };

  13. #13
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Points : 2 757
    Points
    2 757
    Par défaut
    tes deux classes doivent être déclarées de cete façon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef C1_H
    #define C1_H
     
    #include "C2.h"
     
    class C1
    {
    	C2 v2;
    ...
    };
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef C2_H
    #define C2_H
     
    #include "C1.h"
     
    class C2
    {
    	C1 v1;
    ...
    };
     
    #endif
    la déclaration anticipée de type ne fonctionne que lorsqu'on déclare un pointeur sur ce type.

  14. #14
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Hmm... Là ça ne compilera pas (inclusions cycliques), mais en plus ce genre de classes est impossible : elles auraient une taille infinie. A contient un B, qui contient un A, qui contient à son tour un B, qui contient lui-même un A, qui contient un B, qui ...

    A noter que la déclaration anticipée fonctionne aussi pour les références.

  15. #15
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    D'après l'exemple sur les entiers donnés par Moncoulin, je suppose une erreur de conception par rapport à "l'habitude" (et à l'héritage) qui lui pose problème :
    M. décrit l'Ensemble sur lequel il travaille (les entiers) comme l'union des entiers pairs (avec leurs méthodes et propriétés) et des entiers impairs (avec leurs méthodes et propriétés). Il est alors délicat de décrire les méthodes et propriétés de l'Ensemble sans identifier le sous-ensemble auquel appartient un élement.
    La démarche habituelle est de décrire l'ensemble (avec ses méthodes et propriétés, classe de base) puis de spécialiser en décrivant les entiers pairs ( avec les méthodes et propriétés de l'Ensemble + les spécialisations requises, classe dérivée) et les impairs (idem)
    La description est inversée.
    Maintenant si on translate tous ces éléments de B de un, ils deviennent tous pairs et correspondent tous à la classe A: mon objet issu de la classe B est maintenant un objet se référant totalement à A.
    D'où la nécessité d'assurer une conversion de type.
    M souhaite faire changer de type une variable ce qui est impossible en c(++). Un objet a un type constant. Tout ce qu'on peut dire c'est que si A est une spécialisation de B (dérive de B) alors il a aussi le comportement (donc aussi le type) de B et peut être aussi vu comme un type B.
    Il faut sans doute revoir la conception de la représentation des données qui est inadaptée au concept d'héritage plutôt que chercher des artifices satisfaisant la syntaxe et le fonctionnement du langage

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 26
    Points : 25
    Points
    25
    Par défaut
    Il ne faut plus parler d'héritage puisque ce point a déjà été écarté.

    La description a été "inversée", plutôt choisie dans le but cité avant, d'illustrer la perte d'information par formulation.

    J'aimerais plus de précisions sur l'impossibilité de transtypage.

    Pour l'instant, un des "changements" de type est assuré par constructeur (on va dire B (const & A)) l'autre par une surdéfinition de l'opérateur d'affection A=B.

    N'y a t'il pas un changement formel de type par création d'un nouvel objet du type voulu?

  17. #17
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    N'y a t'il pas un changement formel de type par création d'un nouvel objet du type voulu?
    A strictement parler non; Il y a un nouvel objet d'un nouveau type. On a alors 2 objets de types différents.
    Si tu as une procédure logique pour obtenir un deuxième objet du type B à partir du premier du type A , et réciproquement, pourquoi pas. Mais ensuite tu as deux objets, que fais tu du "vieux" ? Comment s'assurer que la donnée est représentée à un instant par le premier ou par le second objet ? Cela doit poser pas mal de problèmes ensuite pour suivre le fil .

    Tu utilises pour cela un constructeur, dans un sens, une surcharge de l'assignation dans l'autre sens. Il te reste aussi la possibilité de surcharger l'opérateur de cast si tu veux absolument transtyper. Mais il faut l'écrire, aucun opérateur cast par défaut ne peut faire l'affaire

Discussions similaires

  1. [DATE][CONVERSION] du type numerique au type date
    Par hamed dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 06/04/2005, 16h16
  2. Conversion de type
    Par sovitec dans le forum Langage
    Réponses: 5
    Dernier message: 15/12/2004, 14h29
  3. Conversion de type
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 06/07/2004, 10h30
  4. [MYSQL] conversion de type sur import de script
    Par sebos63 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/08/2003, 10h00
  5. Réponses: 2
    Dernier message: 05/06/2002, 12h29

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