了解C ++中的转换

时间:2015-11-10 03:52:39

标签: c++ casting type-conversion

我来自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风格的演员表?

3 个答案:

答案 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的无法获取的(私有)基础,则不允许使用强制转换。另一个区别是,在没有运行时检查的情况下允许向下转换(如果aB的派生类,它允许转换,即使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铸造。