6
votes

C ++ bonne façon de static_cast

static_cast code> ne lancera pas une exception. Mais si cela ne réussit pas, cela produira un résultat indéfini. Quel est le moyen le plus approprié de vérifier si la distribution a réussi?

Cela vous aidera-t-il? P>

NewType new_typ_obj = static_cast<NewType>(obj); 

if (new_typ_obj)
    new_typ_obj.do();


1 commentaires

Une manière appropriée de moulage statique est Ne pas (Cast du tout).


4 Réponses :


10
votes

static_cast ne vous donne pas d'informations sur le succès. Si vous avez besoin de faire de type dynamique, utilisez dynamic_cast ou une bibliothèque comme Boost.


0 commentaires

7
votes

Dans l'exemple que vous donnez, que static_cast pourrait jeter une exception en fonction des types impliqués, par exemple si le constructeur de newtype . S'il n'existe pas de chaîne de conversion du type de obj sur newtType , il ne compilera même pas.

Vous pouvez penser à utiliser static_cast pour convertir un pointeur-de-base en un pointeur à dérivé, ce qui est le cas que dynamic_cast vérifie. Il n'y a aucun moyen de dire si static_cast réussit dans ce cas. C'est votre responsabilité que le programmeur ne l'utilise que si c'est correct.


0 commentaires

4
votes

A static_cast n'a qu'un comportement non défini lorsque vous moulez entre le pointeur, la référence ou le pointeur aux types de membres. Il se produit lorsque vous exécutez un bosselé sur un type qui n'est pas vraiment le type de l'objet pointé à l'adresse.

Dans votre exemple, sauf si newtType est un type Typef d'un pointeur ou d'un type de référence et obj est également de ces types, le compilateur vous donnera une erreur si le casting est invalide.

Effectuer si (new_typ_obj) n'a pas de sens pour vérifier si la distribution a été réussie dans tout static_cast . Si newtType n'est pas l'un de ces types polymorphiques, alors en utilisant new_type_obj comme une condition ne fonctionne que si vous avez un moyen de le convertir en bool ( ou il est bool ). Même si c'est le cas, cela n'a rien à voir avec le casting. Si vous êtes plutôt static_cast par des pointeurs sur une hiérarchie d'héritage, alors static_cast ne vous donnera aucune information sur la question de savoir si elle a réussi. Pour cela, vous voulez dynamic_cast .


0 commentaires

1
votes

static_cast ne compilera pas si le type que vous souhaitez lancer n'est pas associé au type que vous souhaitez lancer. Sauf avec void * qui est lié à tous les types. Ainsi, static_cast est toujours une excellente assurance, à l'heure de la compilation.

Il y a toujours le danger de faire un mauvais baisse.

Ma règle personnelle est de:

  • préférez utiliser static_cast pour Upcast (montrer l'intention)
  • préférez utiliser dynamic_cast pour avoir été négativement et vérifier la valeur renvoyée.

    La dernière règle peut être faite avec si le statique_cast pour un refuge est sans danger.


9 commentaires

Sachez que "toujours utilisé dynamic_cast for down Cast" ne fonctionne que si la classe de base est toujours polymorphe. Donc, il dépend de la règle d'une autre règle de style, "seulement éteint aux bases polymorphes". Cette deuxième règle a du sens dans beaucoup de projets mais pas nécessairement tous.


@Stevejessop Mais si la classe de base n'est pas polymorphe, dynamic_cast retournera simplement NullPtr. (bien sûr, il n'a pas beaucoup de sens de l'utiliser)


"Alway usage dynamic_cast pour la descente" est tout simplement faux. Il y a des cas légitimes où vous savez à la compilation que le casting va réussira et vous devez faire cette hypothèse explicite en utilisant static_cast . Ne pas faire cela est objectivement mauvais.


@Konradrudolph J'ai édité "toujours" à "préférer". Est-ce que ça se sent toujours tellement faux?


@StephaneRolland Je peux vivre avec ça.


@Stevejessop avec classe polymorphe, il est de comprendre la classe de base avec plus d'une classe enfant?


@StephaneLandolland comment vous vérifier après dynamic_cast ? Y a-t-il un moyen de le faire que, à coup sûr, fonctionnera à tout moment n'importe où?


@antitrust à l'exécution, dynamic_cast <> renvoie nullptr si jamais le bowncast est incorrect. Donc, vous comparez simplement la valeur de votre pointeur s'il est NULL / NULLPTR.


@antitrust: une classe de base polymorphe signifie un qui comporte au moins une fonction virtuelle . Peu importe le nombre de classes dérivées qu'il a, bien que le nom anticipe que cela puisse en avoir beaucoup.