<windows.h>
标题带有自己的BOOL
types。 在实现中偷看,看起来FALSE
只是一个0
的macros,而TRUE
只是一个macros,但我不确定这是否被指定。
什么是将BOOL
转换为BOOL
的惯用方法? 我可以想像很多可能的方法:
bool a = static_cast<bool>(x); bool b = x ? true : false; bool c = (x == TRUE); bool d = (x != FALSE); bool e = !!x; // ...
不需要任何明确的转换:
BOOL x = some_value; bool b = x;
将数值类型隐式转换为bool
将为0
值为false
,对于任何非零值则为true
。
顺便提一句,你告诉我们<windows.h>
如何定义FALSE
和TRUE
。 它如何定义BOOL
? (从你的评论,这是typedef int BOOL;
)
但是一些编译器可能会警告这种隐式转换,即使它是完全有效的代码。 编译器可以自由地警告任何他们喜欢的东西,包括用来编写代码的难看的字体。 例如,g ++不会抱怨转换,即使是:
g++ -std=c++11 -pedantic -Wall -Wextra ...
但是根据这个在线Visual C ++编译器 ,VC ++确实会产生一个警告:
warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
即使使用static_cast
,它仍然会产生警告。
你可以通过使用!!x
或x ? true : false
来避免这个警告x ? true : false
x ? true : false
。 但我不确定治愈好于疾病。
做到这一点的简单而正确的方法是简单地分配值,并依靠隐式转换来做正确的事情(它会)。
如果您有额外的要求来避免编译器警告,那么这成为更多关于Visual C ++而不是C ++语言的问题。 在不改变源头的情况下,也可能有某种方法来禁止某些警告 – 尽管这样做有可能在实际上有意义时丢失相同的警告。 DieterLücking在评论中建议:
#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
但看起来还是需要修改源代码。 也许有一些相同的东西没有。
还有一件事:由于BOOL
实际上是int
类型,所以这个建议的解决方案是:
bool c = (x == TRUE);
并不等同于其他人。 任何非零int
都被视为true,但只有值1
等于 TRUE
。 例如,如果x == 2
,则上面的将c
设置为false
,而if (x)
仍然会将其视为真实条件。 切勿将布尔值的相等性与true
或TRUE
。 (比较它们为false
或FALSE
更安全,但仍然不必要;这就是!
运算符的用途。)
这一切都假设,如果你有一个BOOL
类型的值,你只关心它是真的还是真的(零或非零)。 不幸的是,情况并非总是如此。 Ben Voight的回答指出,微软的API至少包含一个函数GetMessage ,它返回的BOOL
结果不是一个简单的布尔值。 在这种可怕的情况下,如果您需要区分多个非零值,则从BOOL
到bool
转换并不合适。
最后,我责怪微软为已经具有完美表现的内置 其实这不太公平, 它用于需要从C和C ++访问的API。 微软对bool
类型的语言定义了BOOL
类型。BOOL
的定义可能会回到他们的C语言实现上,这在某种程度上是有道理的 – 至少在C99之前,微软仍然不支持。 (我不知道微软的C编译器是否支持_Bool
,即使是这样, _Bool
与int
有一些语义上的区别,改变BOOL
的定义可能会破坏一些代码 – 尤其是使用GetMessage
代码。
我使用一个宏:
#define _bool(b) (!!(b))
海事组织,使我的代码更具可读性。
编辑:一位评论者质疑我在宏名称中使用下划线。 为了解决这个问题,这是一个新的版本,仍然是通用的,仍然使用相同的名称_bool
,但是是符合的,据此。
namespace MyBool { template<typename T> inline bool _bool(const T b) { return !!b; } } using namespace MyBool;
很难说win32程序员怎么做,但恕我直言,它应该通过:
bool c = (X == TRUE);
要么
bool d = (x != FALSE);
我认为这是一个不错的做法,在宏(或任何其他预定义的东西)
恒定。
有一天TRUE可能变成0和FALSE 1;)
没有安全的方法,因为Win32 BOOL
有两个以上的值 。
这是一个有点意见的问题,但是我认为有很多客观的论点可供选择。
最好的选择是:
bool d = (x != FALSE);
这使得读者的意图非常清楚,不依赖于隐式转换,并且明确表示除了一个简单的赋值之外还有更多的工作要做。
第二个最好的选择是:
bool b = x ? true : false;
但是,对于不经意的读者来说,这看起来像是一个同义反复。
我尝试避免在作业中进行隐式转换,因为获取错误的转换是令人惊讶的错误来源。 即使当我知道隐式转换会做正确的事情时,我倾向于明确地做,这可能有助于有人在将来阅读代码。 明确还允许您保持启用转换警告,以便捕获您不知道您(ab)使用的其他隐式转换。
替代品都有更严重的缺陷。
bool a = static_cast<bool>(x);
这就像锤击一个方形的钉子进入一个圆孔。 编写一个自然而然地返回正确类型的表达式会更加优雅。
bool c = (x == TRUE);
与TRUE
进行比较通常是一个坏主意,因为其他非零值将转换为false,这几乎肯定是一个错误。
bool e = !!x;
太聪明了,相比之下,表达你的意思。 (我过去犯了这个罪。)
bool f = x;
MSVC ++对纯隐式转换的性能警告似乎是公平的。 编译器必须生成额外的代码来将int转换为bool。 对于这项额外的工作,这份空白的任务毫无头绪。 如果它在一个紧密的循环,你可能会在意。 (当然, static_cast
选项中的性能警告看起来太过分了,但是我们已经认定这样做不够优雅了。)
d
和b
表达清楚地表达了意图,并且明显地表明在这里比直接指派更多。