现在的位置: 首页 > 综合 > 正文

cpp里, 能否用int来替代bool? 这样bool类型就不需要了

2013年01月31日 ⁄ 综合 ⁄ 共 3813字 ⁄ 字号 评论关闭

拍脑袋容易想到用int来替代,1为true, 0为false.

 

呵呵,很遗憾,答案是不能

 

详见此精彩文章:http://www.gotw.ca/gotw/026.htm

 

Bool
Difficulty: 7 / 10

Do we really need a builtin bool type? Why not just emulate it in the existing language? This GotW shows the answer.

Problem

Besides
wchar_t (which was a typedef in C), bool is the only builtin type to be
added to C++ since the ARM.[1] Could bool's effect have been duplicated
without adding a builtin type? If yes, show an equivalent
implementation. If no, show why possible implementations do not behave
the same as the builtin bool.

Solution

Besides
wchar_t (which was a typedef in C), bool is the only builtin type to be
added to C++ since the ARM.[1] Could bool's effect have been duplicated
without adding a builtin type? If yes, show an equivalent
implementation.

The answer is: No. The bool builtin type
(and the reserved keywords true and false) were added to C++ precisely
because they couldn't be duplicated completely using the existing
language.

If no, show why possible implementations do not behave the same as the builtin bool.

There are four major implementations:

Option 1: Typedef (score: 8.5 / 10)

This option means to "typedef <something> bool;", typically:

    typedef int bool;
    const bool true  = 1;
    const bool false = 0;

This solution isn't bad, but it doesn't allow overloading on bool. For example:

    // file f.h
    void f( int  ); // ok
    void f( bool ); // ok, redeclares the same function

    // file f.cpp
    void f( int  ) { /*...*/ }   // ok
    void f( bool ) { /*...*/ }   // error, redefinition

Another problem is that it can allow code like this:

    void f( bool b ) {
        assert( b != true && b != false );
    }

So Option 1 isn't good enough.

Option 2: #define (score: 0 / 10)

This option means to "#define bool <something>", typically:

    #define bool  int
    #define true  1
    #define false 0

This
is, of course, purely evil. It not only has all of the same problems as
Option 1 above, but it also wreaks the usual havoc of #defines. For
example, pity the poor customer who tries to use this library and
already has a variable named 'false'; now this definitely behaves
differently from a builtin type.

Trying to use the preprocessor to simulate a type is just a bad idea.

Option 3: Enum (score: 9 / 10)

This option means to make an "enum bool", typically:

    enum bool { false, true };

This
is somewhat better than Option 1, in my opinion. It allows overloading
(the main problem with #1), but doesn't allow automatic conversions
from a conditional expression (which would have been possible with #1),
to wit:

    bool b;
    b = ( i == j );

This doesn't work because ints cannot be implicitly converted to enums.

Option 4: Class (score: 9 / 10)

Heck, this is an object-oriented language, right? So why not write an class, typically:

    class bool {
    public:
        bool();

        bool( int );      // to enable conversions from
        operator=( int ); //  conditional expressions

        //operator int();   // questionable!
        //operator void*(); // questionable!

    private:
        unsigned char b_;
    };

    const bool true ( 1 );
    const bool false( 0 );

This works except for the conversion operators marked "questionable". They're questionable because:

1.
WITH an automatic conversion, bools will interfere with overload
resolution, just as do all classes having non-explicit (conversion)
constructors and/or automatic conversions (especially conversions
from/to common types).

2. WITHOUT a conversion to something like int or void*, bool objects can't be tested "naturally" in conditions. For example:

    bool b;
    /*...*/
    if( b ) // error without an automatic conversion to
    {       // something like int or void*
        /*...*/
    }

It's
a classic Catch-22 situation: We must choose one or the other, but
neither option lets us duplicate the effect of having a builtin bool
type.

Summary

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
Option 4: specify that conditional expressions have type bool.

 

Notes

1. M. Ellis M and B. Stroustrup. The Annotated C++ Reference Manual (Addison-Wesley, 1990).


Copyright © 2009
Herb Sutter

抱歉!评论已关闭.