réguliers du casting par rapport static_cast par rapport à dynamic_cast

voix
1k

J'ai écrit C et le code C pendant près de vingt ans, mais il y a un aspect de ces langues que je ne l'ai jamais vraiment compris. J'ai évidemment utilisé des moulages réguliers à savoir

MyClass *m = (MyClass *)ptr;

dans tous les sens, mais il semble y avoir deux autres types de moulages, et je ne sais pas la différence. Quelle est la différence entre les lignes de code ci-dessous?

MyClass *m = (MyClass *)ptr;
MyClass *m = static_cast<MyClass *>(ptr);
MyClass *m = dynamic_cast<MyClass *>(ptr);
Créé 26/08/2008 à 14:20
source utilisateur
Dans d'autres langues...                            


8 réponses

voix
8

dynamic_casta la vérification du type d'exécution et fonctionne uniquement avec des références et des pointeurs, alors que static_castne propose pas la vérification du type d'exécution. Pour plus d' informations, consultez l'article MSDN Opérateur static_cast .

Créé 26/08/2008 à 14:26
source utilisateur

voix
71

Vous devriez regarder l'article C ++ Programmation / clichage .

Il contient une bonne description de tous les différents types de fonte. Le ci-dessous du lien ci-dessus:

const_cast

const_cast (expression) const_cast <> () est utilisée pour ajouter / retirer const (RNS) (ou Etreté volatile) d'une variable.

static_cast

static_cast (expression) static_cast <> () est utilisée pour couler entre les types entiers. 'Par exemple' char-> long, int> court etc.

fonte statique est également utilisé pour lancer des pointeurs vers des types connexes, par exemple la coulée void * le type approprié.

dynamic_cast

cast dynamique est utilisé pour convertir les pointeurs et les références à l'exécution, généralement dans le but de lancer un pointeur ou une référence vers le haut ou vers le bas d'une chaîne d'héritage (hiérarchie d'héritage).

dynamic_cast (expression)

Le type de cible doit être un pointeur ou le type de référence, et l'expression doit évaluer à un pointeur ou de référence. la distribution dynamique ne fonctionne que lorsque le type d'objet auquel l'expression se réfère est compatible avec le type de cible et la classe de base comporte au moins une fonction membre virtuelle. Dans le cas contraire, et le type d'expression étant coulée est un pointeur NULL est renvoyé, si une distribution dynamique sur une référence échoue, est jeté une exception bad_cast. Quand il ne manque pas, retourne un pointeur dynamique coulée ou référence du type de cible à l'objet auquel l'expression fait référence.

reinterpret_cast

Réinterpréter cast jette simplement un type à l'autre au niveau du bit. Tout pointeur ou type intégral peut être casté en tout autre avec le cast de réinterpréter, ce qui permet facilement d'abus. Par exemple, avec une fonte pourrait réinterpréter, unsafely, jeter un pointeur entier à un pointeur de chaîne.

Créé 26/08/2008 à 14:28
source utilisateur

voix
10

Style C jette conflate const_cast, static_cast et reinterpret_cast.

Je souhaite C ++ n'a pas de style C jette. C ++ jette se démarquer correctement (comme ils le devraient, moulages sont normalement indicatif de faire quelque chose de mal) et bien distinguer entre les différents types de conversion qui jette effectuer. Ils permettent également des fonctions similaires d'aspect à écrire, par exemple boost :: lexical_cast, ce qui est tout à fait agréable du point de vue de la cohérence.

Créé 26/08/2008 à 14:38
source utilisateur

voix
20

Pour votre information, je crois que Bjarne Stroustrup est cité comme disant que des moulages de type C doivent être évitées et que vous devez utiliser static_cast ou dynamic_cast si possible.

FAQ de Barne Stroustrup style C ++

Prenez ces conseils pour ce que vous voulez. Je suis loin d'être un gourou C ++.

Créé 26/08/2008 à 14:39
source utilisateur

voix
23

Évitez d'utiliser C-style jette.

moulages de style C sont un mélange de const et réinterprètent la distribution, et il est difficile de trouver et de remplacement dans votre code. Un programmeur d'application C ++ doit éviter coulé le style C.

Créé 19/09/2008 à 18:30
source utilisateur

voix
1k

static_cast

static_castest utilisé pour les cas où vous voulez essentiellement à inverser une conversion implicite, avec quelques restrictions et ajouts. static_castN'a pas de contrôle d'exécution. Cela devrait être utilisé si vous savez que vous faites référence à un objet d'un type spécifique, et donc un chèque ne serait pas nécessaire. Exemple:

void func(void *data) {
  // Conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}

Dans cet exemple, vous savez que vous avez passé un MyClassobjet, et donc il n'y a pas besoin d'un contrôle d'exécution à cet effet .

dynamic_cast

dynamic_castest utile lorsque vous ne savez pas ce que le type dynamique de l'objet est. Elle renvoie un pointeur NULL si l'objet référencé ne contient pas le type casté en tant que classe de base (lorsque vous lancez une référence, une bad_castexception est levée dans ce cas).

if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
  ...
} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
  ...
}

Vous ne pouvez pas utiliser dynamic_castsi vous baissés (CAST à une classe dérivée) et le type d'argument n'est pas polymorphes. Par exemple, le code suivant n'est pas valide, car Basene contient aucune fonction virtuelle:

struct Base { };
struct Derived : Base { };
int main() {
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // Invalid
}

Un « up-cast » (cast à la classe de base) est toujours valable à la fois static_castet dynamic_cast, et aussi sans aucun casting, comme « up-cast » est une conversion implicite.

Cast régulier

Ces moulages sont également appelés fonte style C. Un casting de style C est fondamentalement identique à essayer une gamme de séquences des moulages de C, et en prenant la première fonte du C ++ qui fonctionne, sans jamais considérer dynamic_cast. Inutile de dire que cela est beaucoup plus puissant car il combine tous const_cast, static_castet reinterpret_cast, mais il est aussi dangereux, car il ne se sert pas dynamic_cast.

De plus, style C moulages non seulement vous permettre de le faire, mais ils vous permettent également de toute sécurité jeté sur une base de classe privée, alors que le « équivalent » static_castséquence vous donnera une erreur de compilation pour cela.

Certaines personnes préfèrent le style C jette en raison de leur brièveté. Je les utilise pour numérique moulages seulement, et utiliser le C ++ approprié lorsque les types jette définis par l'utilisateur sont impliqués, car ils fournissent un contrôle plus strict.

Créé 10/08/2009 à 14:50
source utilisateur

voix
7

dynamic_castprend en charge uniquement les types pointeur et référence. Elle retourne NULLsi la distribution est impossible si le type est un pointeur ou lance une exception si le type est un type de référence. Par conséquent, dynamic_castpeut être utilisé pour vérifier si un objet est d'un type donné, static_castne peut pas (vous simplement se retrouver avec une valeur non valide).

C style (et d'autres) moulages ont été couverts dans les autres réponses.

Créé 05/02/2012 à 18:10
source utilisateur

voix
104

fonte statique

Le casting statique effectue des conversions entre les types compatibles. Il est similaire à la fonte de style C, mais elle est plus restrictive. Par exemple, la distribution de style C permettrait un pointeur entier pour pointer vers char.

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

Etant donné que cela aboutit à un pointeur de 4 octets pointant sur 1 octet de la mémoire allouée, l'écriture de ce pointeur soit provoquer une erreur d'exécution ou écrase un peu de mémoire adjacent.

*p = 5; // run-time error: stack corruption

Contrairement à la fonte de style C, la distribution statique permettra au compilateur de vérifier que le pointeur et les types de données sont compatibles pointée, ce qui permet au programmeur de rattraper cette affectation de pointeur incorrecte lors de la compilation.

int *q = static_cast<int*>(&c); // compile-time error

réinterpréter casting

Pour forcer la conversion du pointeur, de la même manière que les acteurs de style C fait en arrière-plan, la distribution de réinterpréter serait utilisé à la place.

int *r = reinterpret_cast<int*>(&c); // forced conversion

Cette fonte gère les conversions entre certains types non apparentés, tels que d'un type de pointeur à un autre type de pointeur incompatible. Il suffit de réaliser une copie binaire des données sans altérer la configuration binaire sous-jacent. Notez que le résultat d'une telle opération à faible niveau est un système spécifique et donc pas portable. Il doit être utilisé avec prudence si elle ne peut pas être totalement évitée.

fonte dynamique

Celui-ci est uniquement utilisé pour convertir les pointeurs d'objet et les références d'objets dans d'autres types de pointeur ou de référence dans la hiérarchie de l'héritage. Il est le casting seulement fait en sorte que l'objet pointé peut être converti, en effectuant un contrôle d'exécution que le pointeur fait référence à un objet complet du type de destination. Pour cette vérification d'exécution soit possible l'objet doit être polymorphes. Autrement dit, la classe doit définir ou hériter d'au moins une fonction virtuelle. En effet, le compilateur ne génère les informations de type d'exécution nécessaire à ces objets.

Exemples dynamiques de la distribution

Dans l'exemple ci-dessous, un pointeur MyChild est converti en un pointeur MyBase en utilisant une distribution dynamique. Cette conversion dérivée à base réussit, car l'objet enfant comprend un objet de base complète.

class MyBase 
{ 
  public:
  virtual void test() {}
};
class MyChild : public MyBase {};



int main()
{
  MyChild *child = new MyChild();
  MyBase  *base = dynamic_cast<MyBase*>(child); // ok
}

L'exemple suivant tente de convertir un pointeur MyBase à un pointeur MyChild. Étant donné que l'objet de base ne contient pas un objet enfant complète cette conversion de pointeur échouera. Pour indiquer, la distribution dynamique renvoie un pointeur NULL. Cela donne un moyen pratique pour vérifier si oui ou non une conversion a réussi au cours de l'exécution.

MyBase  *base = new MyBase();
MyChild *child = dynamic_cast<MyChild*>(base);


if (child == 0) 
std::cout << "Null pointer returned";

Si une référence est convertie au lieu d'un pointeur, la distribution dynamique puis échouer en lançant une exception bad_cast. Cela doit être gérée à l'aide d'une instruction try-catch.

#include <exception>
// …  
try
{ 
  MyChild &child = dynamic_cast<MyChild&>(*base);
}
catch(std::bad_cast &e) 
{ 
  std::cout << e.what(); // bad dynamic_cast
}

Casting dynamique ou statique

L'avantage d'utiliser une distribution dynamique est qu'il permet au programmeur de vérifier si oui ou non une conversion a réussi au cours de l'exécution. L'inconvénient est qu'il ya une surcharge de performance associée à faire cette vérification. Pour cette raison, en utilisant une distribution statique aurait été préférable dans le premier exemple, parce qu'une conversion à base dérivée ne manquera jamais.

MyBase *base = static_cast<MyBase*>(child); // ok

Cependant, dans le second exemple, la conversion peut réussir ou d'échouer. Il échouera si l'objet MyBase contient une instance MyBase et il réussira si elle contient une instance MyChild. Dans certains cas, cela peut ne pas être connu avant l'exécution. Lorsque tel est le cas cast dynamique est un meilleur choix que fonte statique.

// Succeeds for a MyChild object
MyChild *child = dynamic_cast<MyChild*>(base);

Si la conversion dérivée de base à a été réalisée en utilisant une distribution statique au lieu d'une distribution dynamique de la conversion aurait pas échoué. Il aurait renvoyé un pointeur qui fait référence à un objet incomplet. Déréférencement un pointeur peut conduire à des erreurs d'exécution.

// Allowed, but invalid
MyChild *child = static_cast<MyChild*>(base);

// Incomplete MyChild object dereferenced
(*child);

casting const

Celui-ci est principalement utilisé pour ajouter ou supprimer le modificateur const d'une variable.

const int myConst = 5;
int *nonConst = const_cast<int*>(&myConst); // removes const

Bien que la fonte const permet la valeur d'une constante à modifier, faisant encore un code non valide qui peut provoquer une erreur d'exécution. Cela pourrait se produire par exemple si la constante est situé dans une section de la mémoire en lecture seule.

*nonConst = 10; // potential run-time error

fonte Const est plutôt utilisé principalement quand il y a une fonction qui prend un argument pointeur non constant, même si elle ne modifie pas la pointée.

void print(int *p) 
{
   std::cout << *p;
}

La fonction peut alors être passé une variable constante en utilisant une distribution const.

print(&myConst); // error: cannot convert 
                 // const int* to int*

print(nonConst); // allowed

Source et plus d'explications

Créé 24/08/2013 à 02:55
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more