static_cast和Implicit_cast有什么区别?

16

什么是implicit_cast?何时应该优先使用implicit_cast而不是static_cast?


6
如果您在询问boost :: implicit_cast,请编辑帖子以更清楚地表明。 - Abhay
@Abhay,“implicit_cast”的概念比Boost早几年,它与编程有关。 - curiousguy
1
@curiousguy:像“隐式转换”这样的东西不存在,因为转换始终是显式的请求。有关详细信息,请阅读已接受的答案... - Abhay
@Abhay,“隐式转换”这个想法确实存在,早在 Boost 之前就已经存在了。implicit_cast 模板一次又一次地被提出。它是自然的,而且需要经常看到。它应该真正成为一个标准转换,就像 static/const/reinterpret_cast 一样。 - curiousguy
3
这个想法确实存在,但这里的问题在于使用了“implicit_cast”,它在标准的C++中并不存在,因此需要澄清。 - Abhay
4个回答

19

我从另一个地方的评论中复制过来,以回答这个评论

你可以使用static_cast进行向下转型。但implicit_cast则不行。 static_cast基本上允许您执行任何隐式转换,并且还允许您执行任何隐式转换的反向操作(有一些限制。如果涉及虚基类,则无法向下转型)。但是implicit_cast仅接受隐式转换。不能向下转型,不能使用void*->T*,如果T只有U的显式构造函数,则不能使用U->T

请注意,强制类型转换和类型转换之间的区别非常重要。在以下情况下,没有进行强制类型转换。

int a = 3.4;

但是从double到int会发生隐式转换。像“隐式强制类型转换”这样的事情不存在,因为强制类型转换始终是显式的转换请求。 boost::implicit_cast 的名称构造是“使用隐式转换进行转换”的可爱组合。现在,boost::implicit_cast 的整个实现如下(在此处有解释):

template<typename T> struct identity { typedef T type; };
template<typename Dst> Dst implicit_cast(typename identity<Dst>::type t)
{ return t; }

这个想法是为参数 t 使用非推导上下文。这样可以避免以下陷阱:

call_const_version(implicit_cast(this)); // oops, wrong!

所需内容是这样写出来的:

所需内容是这样写出来的


call_const_version(implicit_cast<MyClass const*>(this)); // right!

编译器无法推断模板参数的类型,因为它首先必须知道>是什么,因为它是用于推断的参数的一部分。但是,它又依赖于参数(对于某些类型,可以显式地专门化identity)。现在,我们得到了一个循环依赖,对于此情况,标准只说这样的参数是无法推导的上下文,并且必须提供显式的模板参数。

4

如果在您的情况下,implicit_cast 足够使用,请尽量使用它。与 static_cast 相比,implicit_cast 功能更少也更安全。

例如,从基类指针向派生类指针的向下转型可以使用 static_cast,但不能使用 implicit_cast。相反地,两种类型的转换都可以使用 implicit_cast。因此,在从基类向派生类进行类型转换时,请使用 implicit_cast,因为它可以在您混淆这两个类的情况下保持安全。

还要记住,通常不需要使用 implicit_cast。在大多数情况下,当 implicit_cast 可以使用时,根本不需要使用任何转换,这就是“implicit”的含义所在。只有在特殊情况下才需要使用 implicit_cast,例如必须精确控制表达式的类型以避免重载等情况。


你在这里把“派生”和“基类”搞反了。一个派生指针总是可以转换为(公共或可访问的)基类,但向下转换需要显式转换。 - Adam H. Peterson
@AdamH.Peterson 没错,我刚刚编辑了答案。 - Bruno Martinez

1

implicit_cast 可以将一种类型转换为另一种类型,并且可以通过编写隐式转换函数来扩展,以从一种类型转换为另一种类型。

例如:

int i = 100;
long l = i;

int i = 100;
long l = implicit_cast<long>(i);

代码完全相同

但是你可以为自己的类型提供隐式转换,方法是重载 implicit_cast,如下所示:

template <typename T>
inline T implicit_cast (typename mpl::identity<T>::type x) 
{
    return x;
}

请点击这里boost/implicit_cast.hpp以获取更多信息

希望这可以帮到您

编辑

此页面还讨论了implicit_cast New C++

另外,static_cast的主要功能是执行从一种类型到另一种类型的非更改或语义转换。类型会发生变化,但值保持不变,例如:

void *voidPtr = . . .
int* intPtr = static_cast<int*>(voidPtr);

我想把这个空指针看作是一个整型指针,但指针本身不会改变,在底层,voidPtr 的值与 intPtr 完全相同。 implicit_cast 可以实现类型转换,但转换后的值可能会有所不同。


1
"static_cast的主要功能是执行从一种类型到另一种类型的非更改或语义转换。类型会发生变化,但值保持不变。在这种情况下(static_cast<int*>),值不会改变;通常,static_cast可以改变类型和值:一个明显的例子是static_cast<int>(3.14)。" - curiousguy

1

隐式转换、显式转换和静态转换都是不同的事情。但是,如果您可以隐式转换,那么您可以显式转换,如果您可以显式转换,那么您可以进行静态转换。然而,在另一个方向上是不成立的。隐式转换和静态转换之间存在完全合理的关系。前者是后者的子集。

有关详细信息,请参见C++标准第5.2.9.3节

否则,如果声明T t(e)对于某些虚构的临时变量t(8.5)是良好形式化的,则表达式e可以使用形式为static_cast(e)的static_cast显式转换为类型T。

C ++鼓励使用static_cast,因为它使得程序中的转换“可见”。使用转换本身表示一些程序员强制执行的规则,这值得一看,所以最好使用static_cast。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接