Question

Je dois convertir un type intégral qui contient une adresse du type de pointeur réelle. Je pourrais utiliser reinterpret_cast comme suit:

MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);

Toutefois, cela ne fonctionne pas de contrôles d'exécution pour voir si l'adresse en question tient en fait un objet MyClass. Je veux savoir s'il y a un avantage dans la première conversion à un vide * (en utilisant reinterpret_cast), puis en utilisant dynamic_cast sur le résultat. Comme ceci:

void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);

Y at-il un avantage à utiliser la deuxième méthode?

Était-ce utile?

La solution

Typage sur dynamic_cast est mis en œuvre de différentes manières par différentes implémentations C ++ de; si vous voulez une réponse à votre implémentation spécifique, vous devez mentionner que la mise en œuvre que vous utilisez. La seule façon de répondre à la question en général est de se référer à la norme ISO C ++.

Par ma lecture de la norme, appelant dynamic_cast sur un pointeur vide est illégal:

dynamic_cast<T>(v)
  

« Si T est un type de pointeur, v doit être un rvalue d'un pointeur pour compléter le type de classe »

(de 5.2.7.2 de la norme ISO C). void est pas un type de classe complète, de sorte que l'expression est illégale.

Fait intéressant, le type étant jeté est autorisé à être un pointeur vide, i.e..

void * foo = dynamic_cast<void *>(some_pointer);

Dans ce cas, le dynamic_cast réussit toujours, et la valeur résultante est un pointeur sur l'objet le plus dérivé pointée par v.

Autres conseils

Non, il n'y a aucun avantage particulier à le faire. Le moment où vous utilisez reinterpret_cast, tous les paris sont ouverts. Il est à vous pour être sûr que la distribution est valide.

En fait, aucun avantage sérieux. Si le vide * des points à quelque chose qui est pas un pointeur vers un objet polymorphes vous rencontrez un comportement non défini (généralement une violation d'accès) immédiatement.

La façon sûre est de tenir un registre de tous les objets MaClasse en direct. Il est préférable de garder cet enregistrement dans un std::set<void*>, ce qui signifie que vous pouvez facilement ajouter, supprimer et éléments de test.

La raison de les stocker sous forme void*s est que vous ne risquez pas Nastyness comme la création de pointeurs de MyClass* de non alignés vos entiers.

  • D'abord « réinterprétant » int à void * est une mauvaise idée. Si sizeof(int) est 4 et sizeof(void *) est 8 (64x système), il est mal formé.

  • De plus dynamic_cast est valable que pour le cas des classes polymorphes.

L'option 1 est votre seul (semi) l'option portable / valide.

Option 2: est pas valide C ++ en tant que dynamic_cast (comme vide est pas autorisé)

.

Au niveau de la mise en œuvre dont il a besoin des informations de type à partir du type de source pour obtenir le type de destination. Il n'y a aucun moyen (ou il peut y avoir aucun moyen) pour obtenir les informations de type source d'exécution d'un vide * en est ainsi pas valable non plus.

dynamic_cast est utilisé pour ČAS haut et en bas de la hiérarchie de type pas de types inconnus.

En marge, vous devriez probablement utiliser void * plutôt que d'un nombre entier pour stocker un pointeur non typé. Il est possible pour un int de ne pas être assez grand pour stocker un pointeur.

La meilleure façon de gérer les pointeurs en C ++ est de les gérer typesafe. Cela signifie:

  • Ne jamais pointeurs de magasin dans quoi que ce soit d'autre qu'un pointeur
  • Évitez les pointeurs vides
  • Ne jamais passer des pointeurs vers d'autres processus
  • envisager weak_ptr si vous prévoyez d'utiliser des pointeurs sur des fils

La raison est: ce que vous envisagez de faire est dangereux et peut être évitée à moins que vous interfacer avec le code viciée (héritage?). Dans ce cas, considérer la réponse de MSalters, mais sachez qu'il est toujours embêtant.

Si vous êtes sûr que les points de the_integer à une classe de base connue (qui a au moins un membre virtuel), il pourrait en fait être un avantage: sachant que l'objet est d'une classe dérivée spécifique. Mais vous auriez à reinterpret_cast à votre classe de base d'abord, puis faites le dynamic_cast:

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

L'utilisation d'un void* dans dynamic_cast est inutile et tout simplement faux. Vous ne pouvez pas utiliser dynamic_cast pour vérifier s'il y a un objet valide à un emplacement arbitraire dans la mémoire.

Vous devez également faire attention lors de l'enregistrement des adresses dans des variables de type non-pointeur. Il existe des architectures où sizeof (void *)! = Sizeof (int), par exemple LP64.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top