2009-07-13 4 views
2

J'ai un opérateur de conversion qui retourne un pointeur const, et j'ai besoin de const_cast. Cependant, cela ne fonctionne pas, au moins sous MSVC8. Le code suivant reproduit mon problème:Pourquoi ne puis-je pas const_cast le retour de l'opérateur de conversion?

class MyClass { 
public: 
    operator const int*() { 
     return 0; 
    } 
}; 

int main() { 
    MyClass obj; 
    int* myPtr; 
    // compiles 
    const int* myConstPtr = obj; 
    // compiles 
    myPtr = const_cast<int*>(myConstPtr); 
    // doesn't compile (C2440: 'const_cast' : cannot convert from 'MyClass' to 'int *') 
    myPtr = const_cast<int*>(obj); 
} 

Pourquoi est-ce? Cela semble contre-intuitif. Merci!

+1

Etes-vous vraiment en train d'essayer de retourner un pointeur nul avec 'const int *'?C'est aussi une mauvaise habitude de pouvoir transformer une classe en un pointeur vers une primitive. (Par exemple, 'std :: string' ne peut pas être converti en' const char * 'mais fournit une méthode' .c_str() 'qui retourne un pointeur sur ses données .C'est beaucoup plus sûr car alors le programmeur doit être très conscient de ce qu'il fait.) –

+0

@Seth: Merci. Ce n'est pas mon vrai code; c'est juste quelque chose que j'ai écrit pour reproduire l'erreur que je reçois! Rassurez-vous, je ne renvoie pas de pointeurs null dans le but :-) Dans mon cas, la classe est un wrapper fin autour d'un tableau d'octets, et j'aimerais que ses clients l'utilisent comme s'il s'agissait d'un seul. –

+0

Si vous avez l'intention que les utilisateurs puissent manipuler le bytearray directement, alors vous devriez leur donner un opérateur non-const int *() '. En général, donner seulement la version const implique que vous autorisez les lectures mais pas les modifications. Forcer les utilisateurs à faire un 'const_cast' est une erreur dans mon livre. –

Répondre

4

Pour le faire, vous devez encore faire:

myPtr = const_cast<int*>(static_cast<const int*>(obj)); 

Lorsque vous const_cast directement, le regard du compilateur pour l'opérateur coulé à int *.

1

Vous pouvez uniquement utiliser const_cast pour convertir un pointeur non-const du même type (pour éliminer la constité). Pour effectuer un cast entre des types différents, vous avez besoin de reinterpret_cast.

+0

Merci! Je pensais juste que le compilateur découvrirait que 'MyClass' peut être converti en' int * 'automatiquement, comme dans' 'const int * myConstPtr = obj'" –

+1

Non, non, non! Il a créé l'opérateur de conversion de MyClass en int * donc les types * sont * liés. static_cast est approprié. reinterpret_cast n'invoque pas l'opérateur. Heureusement, il ne sera pas compilé car obj n'est pas un pointeur et reinterpret_cast nécessite un pointeur ou un type entier et obj n'est ni l'un ni l'autre. –

-1

Probablement qu'il serait plus clair de votre compilateur si vous faites quelque chose comme:

myPtr = const_cast<int*>(obj()); 

Je ne l'ai pas encore essayé, la pensée.

EDIT: pas Au cas où la déclaration de l'opérateur quelque chose comme:

const int* operator() { 
+0

Ne fonctionne pas: C2064: le terme n'évalue pas une fonction en prenant 0 arguments. –

+0

J'ai toujours utilisé: const int * operator() {) {...} - je ne sais pas d'où vient la définition de la fonction OP, mais apparemment elle compile. –

+0

La définition de l'OP est celle d'un opérateur de conversion à const int *. La définition de Samir est de l'opérateur "function call"() ne prenant aucun paramètre et renvoyant const int *. Bien que les deux opérateurs aient les mêmes entrées et sorties, ils sont utilisés par le compilateur dans différentes situations. –

1

Pensez const_cast<> comme un modèle de fonction

template <typename Target, typename Source> 
Target const_cast(Source src); 

(ce n'est pas la façon dont il est mis en œuvre, mais ça aide ici à imaginez-le). Puis Source est déduit comme MyClass, et il n'y a rien const_cast peut faire pour obtenir un int * à partir d'un MyClass.

Ce que vous voulez est une des conditions suivantes:

const_cast<int*>(static_cast<const int*>(obj) /* invokes operator const int* */); 
// or 
const_cast<int*>(obj.operator const int*()); 
+0

Oui, 'myPtr = const_cast (obj.operator const int *());' fonctionne! C'est un morceau de code laid, cependant. –

1

const_cast ne peut changer que la constance d'un type. Si vous voulez appeler l'opérateur implicite, vous avez besoin d'un static_cast puis d'un const_cast. Bien que ce soit ennuyeux, il s'assure que vous êtes explicite dans ce que vous faites.

myPtr = const_cast<int*>(static_cast<const int*>(obj)); 

Vous pouvez également utiliser l'ancienne école de style c casting opérateur

myPtr = (int*)(const int*)obj; 

Mais cela est fortement déconseillée pour plusieurs raisons:

  • Il ne grepable
  • Vous peut très facilement faire plus que prévu. La plupart du temps, vous ne voulez pas jouer avec les opérations de type const_cast et en utilisant static_cast applique ceci. En fait, vous voulez très rarement un const_cast. Si vous vous trouvez en train de le faire régulièrement, vous avez des erreurs de conception.

Modifier: J'étais légèrement éteint, je l'ai réparé maintenant. Cela rend la distribution de style c un peu plus laide

+1

La distribution de style C est également déconseillée dans ce cas, car elle ne compile pas. Il essaie de lancer une instance de MyClass, pas un pointeur. –

+0

lol, whoops, je l'ai réparé maintenant. –

Questions connexes