2010-11-06 36 views
1

Non seulement cela est valable et ne donne pas d'avertissement même avec -Wall:Pourquoi cette bizarre compatibilité de bool et de pointeurs en C++?

void* p = false; // actually 'true' doesn't work here 
bool b = "Hello, Boolean!"; 

mais aussi cette règle de compatibilité permet la sélection d'une fonction/opérateur surchargé pour un mauvais type. Disons que vous avez surchargé votre operator << pour tous les types fondamentaux et vous avez oublié de surcharger le pointeur vide, alors le compilateur peut sélectionner la version qui prend bool, ou l'inverse.

Alors qu'est-ce qui rend cette règle de compatibilité plus importante que les effets secondaires bizarres (et hautement indésirables) avec des fonctions surchargées?

(Edit: suppression de toutes les références à C, ils ont eu tort: ​​les règles de conversion sont fondamentalement les mêmes en C.)

+1

Le langage C avant C99 n'a pas de type 'bool' natif intégré - il est parfois émulé via' # define'. Dire que "C peut gérer cela correctement" n'a pas beaucoup de sens. –

+0

@In silico: En C, il existe un type '_Bool' intégré. – dreamlax

+0

@dreamlax: Droit. J'ai oublié de mentionner que le langage C avant C99 ne l'avait pas. Cependant, l'OP a utilisé 'bool' au lieu de' _Bool', donc j'ai supposé que l'OP utilisait un 'bool' émulé. –

Répondre

7

Que voulez-vous dire par « C peut gérer cela correctement »? C n'autorise pas la surcharge de fonctions, donc vous êtes assuré d'avoir la booléenne < -> pointeur de conversion dont vous vous plaignez.

Demandez-vous pourquoi cette conversion existe? Le premier n'est pas réellement un bool -> pointeur de conversion, mais reconnaît que le false littéral signifie 0, qui est une valeur de pointeur valide. C'est pourquoi cela ne fonctionne pas avec true, et cela ne fonctionne pas avec une variable bool.

Le second est parce qu'il est agréable de pouvoir écrire:

if (p) 

au lieu de

if (p != 0) 

pour vérifier si un pointeur contient une valeur de pointeur NULL.

EDIT: Les règles de la norme influence T* p = false;:

Une constante de pointeur null est une expression constante intégrale prvalue de type entier qui évalue à zéro

et

Types bool, char, char16_t, char32_t, wchar_t, et les types entiers signés et non signés sont collectivement appelés types entiers. Un synonyme de type intégral est un type entier.

et

Les booléennes sont les mots-clés faux et vrai. De tels littéraux sont prvalues ​​et ont le type bool.

+0

Je ne crois pas que cette compatibilité existe simplement parce que 'si (p)' semble bien (ce que je suis d'accord, c'est le cas). Donc, si false et zero jouent bien avec des pointeurs, cela n'explique pas pourquoi vous ne pouvez pas assigner de pointeurs à ints mais vous pouvez les assigner à des variables bool. – mojuba

+0

Eh bien, la conversion pointeur -> bool a quelques autres manifestations communes ... 'do {} while (p = p-> next);' ou 'p && p-> dostuff();' Et vous pouvez assigner des pointeurs à d'autres types intégraux, ce n'est pas implicite. –

+2

@Mojuba, il y a une conversion pointeur-bool, et il y a une conversion bool-to-int. Mais le compilateur n'effectuera pas deux conversions implicites ensemble, donc vous n'obtiendrez pas de conversion pointeur-à-int. Faites la première conversion explicite, et vous êtes OK: 'int x = (bool) ptr;' –