I motivi principali sono:
1. I casi d'uso per i booleani sono estremamente comuni.
Assumerò la nota convenzione che 0 significa falso e 1 significa vero ne è una prova sufficiente.
2. Vogliamo sicurezza dei tipi.
Un intero può fare tutto ciò che un booleano può fare, e molto altro ancora, quindi non è che ci mancassero delle funzionalità.
Ma se usassimo interi per rappresentare i booleani, i nostri "booleani" sarebbero in grado di fare cose che i booleani non dovrebbero essere in grado di fare (come addizione e sottrazione), e sarebbero in grado di interagire con "interi reali" in modi che non hanno alcun senso (in senso stretto, true non dovrebbe essere uguale a 1).
Di solito usiamo il termine "sicurezza del tipo" per riferirci a problemi come questo. Usare gli interi per rappresentare i booleani non è una soluzione "sicura per il tipo".
La sicurezza del tipo è generalmente considerata una buona cosa molto , specialmente in linguaggi tipizzati staticamente, in cui il compilatore controlla efficacemente il tuo programma per errori di tipo su ogni compilation. Dato che true == 42
non è un confronto valido o significativo, sarebbe bello se il compilatore semplicemente non lo permettesse e ci costringesse a risolvere quel pezzo di codice. Il "miglioramento della leggibilità" che menzioni nella tua domanda è un altro vantaggio tipico.
3. Un tipo definito dall'utente (cioè una classe o una struct) non può rappresentare correttamente un booleano, quindi dovrebbe essere un tipo primitivo o predefinito
Per molti di noi questa è la parte davvero interessante e non ovvia. Nel caso del C ++, questo problema è spiegato in modo approfondito dal Guru della settimana # 26 di Herb Sutter . Citerò il suo riassunto qui:
A typedef ... bool wouldn't allow overloading on bool.
A #define bool wouldn't allow overloading either and would wreak the
usual havoc of #defines.
An enum bool would allow overloading but couldn't be automatically
converted from a conditional expression (as in "b = (i == j);").
A class bool would allow overloading but wouldn't let a bool object be
tested in conditions (as in "if( b )") unless it provided an automatic
conversion to something like int or void*, which would wreak the usual
havoc of automatic conversions.
Yes, we really did need a builtin bool! And, finally, there's one more
thing (related to overloading) that we couldn't have done otherwise,
either, except perhaps with [a class]: specify that conditional
expressions have type bool.
Quindi il C ++ non può fare booleani non primitivi. A rischio di semplificare eccessivamente le differenze tra le lingue, se non si può fare qualcosa in C ++, ci sono buone possibilità che non si possa farlo in nessuno degli altri linguaggi OOP tradizionali. Credo che l'implementazione di C # potrebbe essere esattamente simile a quella di C ++, ma non più vicina, e Java sarebbe significativamente peggio poiché non offre intenzionalmente sovraccarico dell'operatore o conversioni implicite.