我正在阅读ROS的代码。
在文件ros_comm/roscpp/include/ros/subscriber.h
中,我看到了这样的一段代码:
operator void*() const { return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; }
好吧,(void *)0
在C语言中可以看作是NULL
,但是(void *)1
是什么意思?
如果类Foo
包含此函数,则意味着我们可以这样编写代码:
Foo foo;
void *ptr = foo;
对吗?那么这是否意味着void *ptr = (void *)1
是可能的?这是什么意思?
答案 0 :(得分:58)
这是避免在C ++ 11中引入bool
上下文转换之前隐式转换为explicit
的问题的老技巧。它旨在用于检查有效性:
Subscriber my_subscriber = someFunction();
if (!my_subscriber) {
// error case
}
重要的一点是,从void*
到整数类型不存在任何内置转换,但从bool
到整数类型却没有内置转换。同时,存在从void*
到bool
的内置转换。这意味着,如果您定义了对bool
的隐式转换,则以下内容出奇地有效:
void my_func(int i);
void another_func() {
Subscriber sub = something();
my_func(sub);
}
将转换定义为void*
可以避免该问题。
这些天这些技巧已经过时了。 C ++ 11引入了explicit
转换。在explicit
和循环的情况下考虑将bool
转换为if
,但在其他有问题的情况下则不考虑。这意味着这些天的转换应写为:
explicit operator bool() const { return impl_ && impl_->isValid(); }
答案 1 :(得分:0)
表明编写代码的人对他们使用的语言或工具不是很熟悉,或者代码已经存在了很长时间,并且被不同的人破解了。在过去的某个时候经历了从C到C ++的过渡,但仍带有一些旧的API合同(期望void*
),可能难以更改。
如果您查看源代码,则没有好理由这样做。 impl_
是实现boost::shared_ptr<Impl>
的{{1}},并且operator bool
也返回Impl::isValid
。除了bool
之外,没有理由使用或返回任何内容。
基本上,这是一种扭曲的(并且可能是危险的)书写方式:
bool