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 :

dynamic_cast() sur pointeur de pointeur


Sujet :

C++

  1. #1
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut dynamic_cast() sur pointeur de pointeur
    Bonjour,

    On me fournit 2 interfaces qui correspondent au design pattern Factory. Ces interfaces, je vais les appeler B1 pour la fabrique et B2 pour le produit. Ces 2 interfaces étant évidemment virtuelles, je crées des classes qui dérivent de celles-ci, D1 pour la fabrique concrète et D2 pour le produit concret.

    Voici un exemple simplifié de 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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #include <iostream>
    #include <list>
    
    using namespace std;
    
    class B2
    {
    public:
    	virtual ~B2() = 0 {}
    
    	virtual void Display() const { cout << "Je suis B2" << endl; }
    };
    
    class B1
    {
    public:
    	virtual ~B1() {}
    
    	void CreateB2(B2 ** lplpB2) const { *lplpB2 = NewObject(); }
    	virtual B2 * NewObject() const = 0 {}
    	virtual void Display() const { cout << "Je suis B1" << endl; }
    };
    
    class D2 :
    	public B2
    {
    public:
    	D2() : m_iVal(0) {}
    	~D2() {}
    
    	void SetValue(int iVal) { m_iVal = iVal; }
    	void Display() const { cout << "Je suis D2 avec la valeur " << m_iVal << endl; }
    
    private:
    	int m_iVal;
    };
    
    class D1 :
    	public B1
    {
    public:
    	~D1() {}
    
    	void CreateD2(D2 ** lplpD2, int iVal = 0) { CreateB2(reinterpret_cast<B2 **>(lplpD2)); if (*lplpD2) (*lplpD2)->SetValue(iVal); }
    	B2 * NewObject() const { return new D2; }
    	void Display() const { cout << "Je suis D1" << endl; }
    };
    
    void test1()
    {
    	cout << "test1:" << endl;
    
    	D1 d1;
    	D2 * lpD2;
    	d1.CreateD2(&lpD2, 3);
    
    	if (lpD2)
    	{
    		lpD2->SetValue(3);
    		lpD2->Display();
    		delete lpD2;
    		lpD2 = NULL;
    	}
    	else
    	{
    		cerr << "Impossible de creer un objet d2" << endl;
    	}
    }
    
    void test2()
    {
    	cout << "test2:" << endl;
    
    	D1 d1;
    	D2 * lpD2;
    	lpD2 = dynamic_cast<D2 *>(d1.NewObject());
    
    	if (lpD2)
    	{
    		lpD2->SetValue(3);
    		lpD2->Display();
    		delete lpD2;
    		lpD2 = NULL;
    	}
    	else
    	{
    		cerr << "Impossible de creer un objet d2" << endl;
    	}
    }
    
    int main()
    {
    	test1();
    	test2();
    
    	return EXIT_SUCCESS;
    }
    B1 fabrique des B2 à partir de la fonction CreateB2(). La méthode virtuelle NewObject() permet de créer l'objet concret (défini dans les classes dérivées).

    Dans la classe D2, je crée la fonction CreateD2(), je fais appel à la fonction CreateB2() afin de fabriquer mes produits. Je dois donc faire un downcast de D2 ** vers B2 **. J'aimerais utiliser un dynamic_cast() que je pense plus propre vu qu'il s'agit d'un conversion d'un objet polymorphique, mais seul un reinterpret_cast() fonctionne.

    Dans l'exemple, j'ai mis la méthode NewObject() en public au lieu de protected pour tester un dynamic_cast() directement sur le pointeur dans test2(), et là pas de souvis.

    Donc pourquoi je ne peux pas faire de dynamic_cast() quand je passe mon produit D2 par pointeur de pointeur dans la fonction CreateD2()?

    Merci d'avance.

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Pour les méthodes Create ne renvoient pas tout bêtement le truc créé plutôt que de vouloir passer un pointeur de pointeur en paramètre ?
    Sinon si vraiment tu veux faire ça comme ça je pense qu'une référence sur un pointeur irait mieux...

    MAT.

  3. #3
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut
    J'utilise une librairie existante. Dans le cas concret, il s'agit d'un manager de threads. Je dois utiliser la fonction int CreateThread(CWorkingThread ** lpNewThread, bool bCreateSuspended = true, bool IsPoolThread = false); qui crée un thread et gère également pas mal de mécanismes internes. Donc je n'ai pas le choix, je passe par cette méthode qui a comme paramètre un pointeur de pointeur vers le thread crée par la méthode.

  4. #4
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Dans la classe D2, je crée la fonction CreateD2(), je fais appel à la fonction CreateB2() afin de fabriquer mes produits. Je dois donc faire un downcast de D2 ** vers B2 **. J'aimerais utiliser un dynamic_cast() que je pense plus propre vu qu'il s'agit d'un conversion d'un objet polymorphique, mais seul un reinterpret_cast() fonctionne.
    Si je comprends bien, tu as :

    D2** ppD2; => un pointeur vers un pointeur de "D2"
    B2** ppB2; => un pointeur vers un pointeur de "B2"

    Et tu aimerais faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ppB2 = dynamic_cast<B2**>(ppD2);
    Si c'est bien ça, c'est normal que ça marche pô !

    Les types D2** et B2** n'ont aucun rapport entre eux (pas d'héritage) car ils pointent vers des types D2* et B2* (D2* ne dérive pas de B2*) et non vers des D2 et B2 (D2 dérive de B2).

    Par contre, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppB2 = dynamic_cast<B2*>(*ppD2);
    Devrait marcher (gaffe aux pointeurs de pointeurs qui pourraient être NULL) car là, on a :

    *ppB2 du type B2*
    *ppD2 du type D2*

  5. #5
    Invité
    Invité(e)
    Par défaut
    Ca ne marchera pas : *ppB2 == *ppD2 mais ppB2 != ppD2. Tu peux par contre essayer ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ppB2 = &(dynamic_cast<ppB2*>(*ppD2));
    Je ne garantis rien, donc fais un assert pour être sûr.

  6. #6
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut
    Citation Envoyé par buzzkaido Voir le message
    Les types D2** et B2** n'ont aucun rapport entre eux (pas d'héritage) car ils pointent vers des types D2* et B2* (D2* ne dérive pas de B2*) et non vers des D2 et B2 (D2 dérive de B2).
    Merci pour l'explication.

    Citation Envoyé par buzzkaido Voir le message
    Par contre, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppB2 = dynamic_cast<B2*>(*ppD2);
    En effet, j'y fais un truc à peu près similaire, j'ai d'abord déclaré un pointeur intermédiaire de type B2 * que j'utilise dans ma fonction CreateB2(), puis je cast le résultat dans mon pointeur de pointeur de type D2 **.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void CreateD2(D2 ** lplpD2, int iVal = 0) { B2 * lpB2; CreateB2(&lpB2); *lplpD2 = dynamic_cast<D2 *>(lpB2); if (*lplpD2) (*lplpD2)->SetValue(iVal); }
    Ainsi j'ai mon utilisation de dynamic_cast() qui est plus propre et sécurisé.

    Citation Envoyé par Joe Dralliam Voir le message
    Ca ne marchera pas : *ppB2 == *ppD2 mais ppB2 != ppD2.
    OK pour la démonstration.

    Citation Envoyé par Joe Dralliam Voir le message
    Tu peux par contre essayer ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ppB2 = &(dynamic_cast<ppB2*>(*ppD2));
    Je ne garantis rien, donc fais un assert pour être sûr.
    error C2102: '&' requires l-value
    Merci pour votre aide, problème résolu

  7. #7
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Pourquoi se balader avec des pointeurs de pointeurs ? Il y a une contrainte particulière qui t'y pousse ?
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  8. #8
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    Pourquoi se balader avec des pointeurs de pointeurs ? Il y a une contrainte particulière qui t'y pousse ?
    Car la librairie que j'utilise est définie ainsi.

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

Discussions similaires

  1. Pointeurs et pointeurs de pointeurs
    Par wallace27 dans le forum C
    Réponses: 10
    Dernier message: 09/04/2015, 22h07
  2. Réponses: 21
    Dernier message: 06/08/2009, 09h31
  3. Réponses: 6
    Dernier message: 26/05/2007, 00h33
  4. Réponses: 6
    Dernier message: 02/11/2006, 16h44
  5. Réponses: 10
    Dernier message: 03/02/2005, 13h09

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