OVH Cloud OVH Cloud

dynamic_cast et reference

5 réponses
Avatar
JBB
J'ai un bout de code du genre:

class CMere
{public:
};
class CFille1 : public CMere
{public:
};

template <class FILLE> void f(CMere * pMere)
{
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
// ...
}
}

Jusque là tout va bien (?).

Maintenant j'aimerais passer en reference:
template <class FILLE> void f(CMere & rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//et la forcement ca compile pas !!
//du coup je fais:
if(dynamic_cast<FILLE *>(&rMere))
{
FILLE & rFille = static_cast<rMere>;
//...
}
//ou alors
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
FILLE & rFille = * pFille ;
}
}
Mais dans les 2 cas je ne trouve pas ça terrible.
Qu'en pensez vous ?

5 réponses

Avatar
Franck Branjonneau
JBB écrivait:

class CMere
{public:
};
class CFille1 : public CMere
{public:
};

template <class FILLE> void f(CMere * pMere)
{
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
// ...
}
}

Jusque là tout va bien (?).


Oui.

Maintenant j'aimerais passer en reference:
template <class FILLE> void f(CMere & rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//et la forcement ca compile pas !!


Je ne vois pas d'erreur.

//du coup je fais:
if(dynamic_cast<FILLE *>(&rMere))
{
FILLE & rFille = static_cast<rMere>;


Ah là j'en vois une.

//...
}
//ou alors
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
FILLE & rFille = * pFille ;
}
}
Mais dans les 2 cas je ne trouve pas ça terrible.
Qu'en pensez vous ?


Quelle est l'erreur sur

FILLE & rFille = dynamic_cast<FILLE &>(rMere);

?

--
Franck Branjonneau

Avatar
Falk Tannhäuser
JBB wrote:

class CMere
{public:


Il faut que cette classe soit polymorphique pour pouvoir utiliser
le dynamic_cast. Par exemple, ajoute ici

virtuel ~CMere() {}

};
class CFille1 : public CMere
{public:
};
[...]

template <class FILLE> void f(CMere & rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//et la forcement ca compile pas !!


C'est à dire ? La seule chose dont il faut tenir compte ici,
c'est qu'en cas d'échec, le dynamic_cast sur une référence
lève une exception du type std::bad_cast tandis que le
dynamic_cast sur un pointeur produit un pointeur NULL.
Cf. § 5.2.7/9
Tu as peut-être désactivé le support pour les exceptions
de ton compilateur ...


Falk

Avatar
JBB
Franck Branjonneau wrote:
JBB écrivait:

class CMere
{public:
};
class CFille1 : public CMere
{public:
};

template <class FILLE> void f(CMere * pMere)
{
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
// ...
}
}

Jusque là tout va bien (?).


Oui.

Maintenant j'aimerais passer en reference:
template <class FILLE> void f(CMere & rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//et la forcement ca compile pas !!


Je ne vois pas d'erreur.
Effectivement ça marche. J'étais allé un peu vite pour tester.

(il fallait rajouter un méthode virtuelle dans mes classes pour activer
le polymorphisme)

//du coup je fais:
if(dynamic_cast<FILLE *>(&rMere))
{
FILLE & rFille = static_cast<rMere>;


Ah là j'en vois une.

//...
}
//ou alors
FILLE * pFille = dynamic_cast<FILLE *>(pMere);
if (pFille)
{
FILLE & rFille = * pFille ;
}
}
Mais dans les 2 cas je ne trouve pas ça terrible.
Qu'en pensez vous ?


Quelle est l'erreur sur

FILLE & rFille = dynamic_cast<FILLE &>(rMere);

?

Du coup, comme je ne veux pas d'exception je fais:

template <class FILLE> void f(CMere & rMere)
{
ASSERT(dynamic_cast<FILLE *>(&rMere))

if (dynamic_cast<FILLE *>(&rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//...
}
}
le if n'étant normalement pas utile car en pratique, je ne vais jamais
appeler la méthode avec le mauvais type.

Merci à tous


Avatar
Falk Tannhäuser
JBB wrote:
Du coup, comme je ne veux pas d'exception je fais:
template <class FILLE> void f(CMere & rMere)
{
ASSERT(dynamic_cast<FILLE *>(&rMere))

if (dynamic_cast<FILLE *>(&rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//...
}
}


Ce triple dynamic_cast n'est ni beau ne très performant -
alors pourquoi pas le classique

template <class FILLE> void f(CMere & rMere)
{
if(FILLE* pFille = dynamic_cast<FILLE*>(&rMere))
{
FILLE rFille = *pFille;
// ...
}else
TraitementDErreur();
}

le if n'étant normalement pas utile car en pratique, je ne vais jamai s
appeler la méthode avec le mauvais type.


Su tu es sûr de cela, tu peux aussi bien continuer avec
dynamic_cast<FILLE&>(rMere).

Falk

Avatar
kanze
Falk Tannhäuser wrote:
JBB wrote:
Du coup, comme je ne veux pas d'exception je fais:
template <class FILLE> void f(CMere & rMere)
{
ASSERT(dynamic_cast<FILLE *>(&rMere))

if (dynamic_cast<FILLE *>(&rMere)
{
FILLE & rFille = dynamic_cast<FILLE &>(rMere);
//...
}
}


Ce triple dynamic_cast n'est ni beau ne très performant -
alors pourquoi pas le classique

template <class FILLE> void f(CMere & rMere)
{
if(FILLE* pFille = dynamic_cast<FILLE*>(&rMere))
{
FILLE rFille = *pFille;
// ...
}else
TraitementDErreur();
}

le if n'étant normalement pas utile car en pratique, je ne
vais jamais appeler la méthode avec le mauvais type.


Su tu es sûr de cela, tu peux aussi bien continuer avec
dynamic_cast<FILLE&>(rMere).


Tout à fait. Et s'il veut l'assertion (chose tout à fait
compréhensible :

template< typename Fille >
void f( Mere& mere )
{
try {
Fille& fille = dynamic_cast< Fille& >( mere ) ;
// ...
} catch ( std::bad_cast const& error ) {
assert( 0 ) ;
}
}

Voire même (ce que je ferais moi-même) :

template< typename Fille >
void f( Mere& mere )
{
assert( dynamic_cast< Fille* >( &mere ) != NULL ) :
Fille& fille = static_cast< Fille& >( mere ) ;
// ...
}

Mais ça ne vaut, évidemment, s'il est sûr que Mere& réfère
réelement à une Fille (et dans le deuxième cas, que l'héritage
n'est pas virtuel).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34