我来自Java,所以当需要调用这样的函数时:
struct A {
int a;
A(int a) : a(a){ }
};
A foo(A a){
return A(a);
}
我倾向于写类似
的东西A a = foo(A(10));
它完美无缺。但我了解到它也可以这样做::
A a = foo(static_cast<A>(10));
即。它强制执行隐式转换。那么,作为一个经验法则,当我们需要利用隐式转换时,我们应该使用static_cast
- 样式吗?或者在某些情况下可能需要功能/ C风格的演员表?
答案 0 :(得分:3)
你永远不需要C ++中的C风格的演员表。至于你的例子,最常见的写作方式是:
A a = foo(A(10));
答案 1 :(得分:2)
这里有两个不同的方面值得(重新)考虑:应该隐含A::A(int)
,以及如何最好地构建A
以传递给foo
。
对于前者,如果不知道A
应该支持的使用情况,就无法做出决定,但是如果不确定,通常建议错误地使用显式构造函数。
对于构造,使用A(10)
(使用C ++ 11,A{10}
也适用),或只使用10
依赖隐式转换。请注意,A(10)
是一个构造函数调用而不是强制转换:没有必要将static_cast<>()
视为首选的强制转换符号。根据C ++标准中的5.4 [expr.cast],旧的C风格的强制转换符号实际上是(T)
cast-expression
。
答案 2 :(得分:2)
当您想要从A
类型转换为B
时,您有两种语法来定义转换:
class B
{
public:
B(A); # Conversion constructor.
};
或
class A
{
public:
operator B(); # Conversion operator.
};
对于像这样的案例:
void f(B b);
int main()
{
A a;
f(a);
}
如果第一个版本存在,它将使用B
作为参数创建类a
的临时对象。如果存在第二个版本(当然,您实现它),它会调用类operator B()
的{{1}}来从A
创建类型为B
的对象。如果两者都存在,编译器会抛出一个模糊错误的消息。
关于向下/向上转换,隐式转换允许向上转换(如果源类型和目标类型是引用/指针),即使目标库是源的无法(私有)基类。隐式转换还允许从非const源类型转换为const目标类型,或者还允许从rvalue转换为lvalue等。
简而言之,这些是隐式转换的规则。更完整的指南(考虑内置与用户定义的类型和内置转换)是here。
如果你使用C ++ - cast:
a
它几乎相同,但存在一些差异:如果f(static_cast<B>(a));
是B
的无法获取的(私有)基础,则不允许使用强制转换。另一个区别是,在没有运行时检查的情况下允许向下转换(如果a
是B
的派生类,它允许转换,即使A
实际上不是a
类型的对象1}})。这是允许的,因为运行时检查很慢,因此,如果您知道B
实际上是a
类型,则可以在没有运行时检查的情况下安全地应用转换。
其他铸件是:
B
仅从const更改为非const而反之。
const_cast<B>(a)
投下一切。几乎没有涉及的规则。如果从reinterpret_cast<B>(a);
到a
的转换不存在,则只需要B
的内存区域,并将其作为a
类型的对象返回。它是最快的演员。
B
使用运行时检查进行向下转换(两种类型都必须是引用或指针)。如果dynamic_cast<B>(a);
的实际类型不是a
(甚至不是真实类型B
的基类),则抛出/返回异常或空指针(根据if { {1}}或a
是引用或指针。)
最后,C-casting:
a
C-casting的作用是尝试不同的铸件(B
除外,并允许铸造到不可能的基类)并使用第一个有效的铸件。我会说C-casting和隐式演员一样强大。
使用funcion调用语法的显式转换:
f((B)a);
相当于行为中的C铸造。