Question

Suis-je raison de penser que des moulages de type C (qui sont découragées) ne sont que reinterpret_casts? En utilisant cette dernière est visuellement frappant et facile à rechercher lors de la recherche de moulages désagréables, et par conséquent il est recommandé plus de style C moulages?

Si jetant const à l'aide const_cast et de l'écriture à un objet à l'origine const est non défini, quel est le but de const_cast?

Remarque: Je sais que Bjarne condamne à juste titre les opérations de coulée qu'ils ne sont pas sûrs et va même dans la mesure de la mention « Un laid opération doit avoir une forme syntaxique laid. " et par conséquent la verbosité des opérateurs de coulée en C ++. Je vais donc essayer de minimiser leur utilisation. Promettre. :)

Était-ce utile?

La solution

Non. Une distribution de C peut faire l'équivalent d'un const_cast, un static_cast, un reinterpret_cast, ou une combinaison de ceux-ci. Dans le cas où ce n'était pas tout à fait assez, il peut aussi le faire au moins un tour mineur que aucune combinaison des moulages les plus modernes peuvent faire du tout!

Vous pouvez utiliser const_cast avec des résultats définis si la variable d'origine est défini sans const, mais tout ce que vous avez est un pointeur const ou référence à cet objet. OTOH, si vous pensez que vous avez une bonne raison d'utiliser un const_cast, les chances sont que vous devriez vraiment regarder au lieu mutable.

Edit: Je suppose que je l'ai dit tout de suite, mais un casting de style C peut se transformer en une une classe de base inaccessible. Par exemple, pensez à quelque chose comme:

[Edit: Je met à jour le code à quelque chose qui va compiler et (généralement) démontrent problème. ]

#include <iostream>

class base1 {
public:
    virtual void print() { std::cout << "base 1\n"; }
};

class base2 {
public:
   virtual void print() { std::cout << "base 2\n"; }
};

class derived : base1, base2 {}; // note: private inheritance

int main() {    
    derived *d = new derived;
    base1 *b1 = (base1 *)d;    // allowed
    b1->print();    // prints "base 1"
    base2 *b2 = (base2 *)d;    // also allowed
    b2->print();    // prints "base 2"

//    base1 *bb1 = static_cast<base *>(d);  // not allowed: base is inaccessible

    // Using `reinterpret_cast` allows the code to compile.
    // Unfortunately the result is different, and normally won't work. 
    base1 *bb2 = reinterpret_cast<base1 *>(d);
    bb2->print();   // may cause nasal demons.

    base2 *bb3 = reinterpret_cast<base2 *>(d); 
    bb3->print();   // likewise
    return 0;
}

Le code en utilisant les reinterpret_casts compilera - mais d'essayer d'utiliser le résultat (au peur que l'un des deux) causera un problème majeur. Le reinterpret_cast prend la Base adresse de l'objet dérivé et tente de le traiter comme si elle était le type d'objet spécifié de base - et depuis (au plus) un objet de base peut effectivement exister à cette adresse, en essayant de le traiter comme l'autre peut / va causer des problèmes majeurs. Edit: Dans ce cas, les classes sont essentiellement identiques, sauf pour ce qu'ils impriment, si bien que quoi que ce soit pourrait se produire, avec la plupart des compilateurs, les deux les deux derniers imprimera sur « base 1 ». Le reinterpret_cast prend tout ce qui se trouve être à cette adresse et essaie de l'utiliser comme type spécifié. Dans ce cas, je l'ai (essayé de) faire que faire quelque chose d'inoffensif mais visible. Dans le code réel, le résultat ne sera probablement pas si jolie.

Le casting de style C fonctionnera comme un static_cast serait si le code avait utilisé l'héritage public au lieu de privé - à savoir qu'il est au courant de l'endroit où dans la classe dérivée chaque objet de classe de base « vit », et ajuste le résultat, de sorte que chaque pointeur résultant fonctionnera parce qu'il a été ajusté au point au bon endroit.

Autres conseils

Non, moulages de type C peuvent agir comme reinterpret_casts, const-casts ou static_casts en fonction de la situation. C'est pourquoi ils sont découragés - vous voyez un casting de style C dans le code et la nécessité de rechercher des détails pour voir ce qu'il va faire. Par exemple:

const char* source;
int* target = (int*)source;// - acts as const_cast and reinterpret_cast at once
//int* target = retinterpret_cast<int*>source;// - won't compile - can't remove const

Rappelez-vous, qu'un casting const peut agir sur autre chose alors l'identifiant d'origine:

void doit(const std::string &cs)
{
    std::string &ms = const_cast<std::string &>(cs);
}

int main()
{
    std::string s;
    doit(s);
}

Ainsi, alors que Doït est loin const coulée, dans cet exemple, la chaîne sous-jacente ne const donc pas un comportement non défini.

Mise à jour

D'accord, voici un meilleur exemple lors de l'utilisation const_cast est pas complètement sans valeur. Nous commençons par une classe de base avec une fonction virtuelle qui prend un paramètre const:

class base
{
public:
    virtual void doit(const std::string &str);
};

et maintenant vous voulez remplacer cette fonction virtuelle.

class child : public base
{
public:
    virtual void doit(const std::string &str)
    {
        std::string &mstr = const_cast<std::string &>(str);
    }
};

En raison de la logique / structure de votre code, vous savez que child::doit ne sera appelée avec des chaînes non-const (et class base n'est pas sous votre contrôle et vous ne pouvez pas le modifier et vous ne pouvez changer la signature de child::doit parce que alors il ne remplacera pas plus base::doit). Dans ce cas, il est sûr de rejettera const.

Oui, cela est risqué. Peut-être que lorsque vous écrivez cela, il est vrai que l'exécution ne sera jamais atteindre child::doit avec une chaîne non const et le code est valide. Mais cela pourrait changer soit tout en maintenant votre programme ou peut-être lorsque vous reconstruisez et prenez la dernière version de class base.

const_cast est utilisé pour enlever const d'un type. Il peut également supprimer volatile. Si l'objet est vraiment const alors le résultat ne peut pas être écrites et encore un comportement bien défini. Si, cependant, il est promu const (par passage dans une fonction const T, const_casting puis retour à la non-const est ok. (Je l'ai trouvé un peu plus d'info )

reinterpret_cast ne peut pas supprimer const ou volatile d'un type.

voir aussi

moulages de type C sont vraiment le marteau de la programmation - vous dire essentiellement le compilateur que la cheville carrée là-bas s'adaptera à travers ce trou rond, peu importe quoi. En ce sens, reinterpret_cast est très similaire.

Le principal avantage que je vois en utilisant le C ++ - les opérateurs de la distribution de style sont qu'ils vous permettent d'exprimer votre intention mieux et permettre au compilateur de toujours quelques vérifications sur l'opération que vous vous demandez à effectuer plutôt que de un size-fits-all fonte style C.

En ce qui concerne const_cast- vous obtenez souvent dans la situation où vous passez un objet autour par référence const simplement parce que l'API vous oblige à le faire. Dites, vous avez la fonction X que les tâches d'une chaîne de C-style:

void X(const char *str) { ... }

Dans cette fonction vous passez le paramètre à une fonction C qui attend un char *, même si elle ne change pas la chaîne. La seule façon d'accueillir ce serait const_cast str.

Je serais très prudent en utilisant toute sorte de casting, souvent, cela montre qu'il ya quelque chose de pas tout à fait raison avec votre conception, mais parfois vous devez convaincre le compilateur que la cheville qu'il regarde est pas aussi carré qu'il assume . Alors seulement, si vous utilisez les opérateurs de la distribution.

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