【问题标题】:Understanding casting in C++了解 C++ 中的强制转换
【发布时间】:2015-11-10 03:52:38
【问题描述】:

我来自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-style?或者在某些情况下可能需要函数/C 样式转换?

【问题讨论】:

标签: c++ casting type-conversion


【解决方案1】:

在 C++ 中,您永远不需要 C 风格的强制转换。至于你的例子,最常见的写法是这样的:

A a = foo(A(10));

【讨论】:

    【解决方案2】:

    这里有两个不同的方面值得(重新)考虑:A::A(int) 是否应该隐含,以及如何最好地构造一个A 以传递给foo

    对于前者,在不知道 A 应该支持的用法的情况下无法做出决定,但如果不确定,通常建议选择使用显式构造函数。

    对于构造,使用A(10)(C++11,A{10} 也可以),或者只使用10 来依赖隐式转换。请注意,A(10) 是构造函数调用而不是强制转换:没有必要将static_cast&lt;&gt;() 视为首选的强制转换符号。根据 C++ 标准中的 5.4 [expr.cast],旧的 C 风格转换符号实际上是 (T) cast-expression

    【讨论】:

      【解决方案3】:

      当您想要将类型从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 作为参数。如果存在第二个版本(当然,你实现了它),它会调用类Aoperator B() 来从a 创建一个B 类型的对象。如果两者都存在,编译器会向您抛出歧义错误消息。

      关于向下/向上转换,隐式转换允许向上转换(如果源和目标类型是引用/指针),即使目标基类是源的不可访问(私有)基类。隐式转换还允许从非 const 源类型转换为 const 目标类型,或者也允许从右值转换为左值等等。

      简而言之,这些是隐式转换的规则。更完整的指南(考虑内置与用户定义的类型和内置转换)是here

      如果您使用 C++ 类型转换:

      f(static_cast<B>(a));
      

      几乎相同,但有一些区别:如果Ba 的不可访问的(私有)基础,则不允许强制转换。另一个区别是允许向下转换而无需运行时检查(如果BA 的派生类,它允许转换,即使a 实际上不是B 类型的对象)。这是允许的,因为运行时检查很慢,因此,如果您知道 a 实际上是 B 类型,则可以安全地应用强制转换而无需运行时检查。

      其他铸件有:

      const_cast<B>(a)
      

      只能从 const 更改为 non-const,反之亦然。

      reinterpret_cast<B>(a);
      

      铸造一切。几乎不涉及任何规则。如果从aB 的转换不存在,它只会占用a 的内存区域并将其作为B 类型的对象返回。它是目前最快的演员。

      dynamic_cast<B>(a);
      

      带有运行时检查的向下转换(两种类型都必须是引用或指针)。如果a 的真实类型不是B(甚至不是a 的真实类型的基类),则抛出/返回异常或空指针(根据aB是引用或指针)。

      最后,C-casting:

      f((B)a);
      

      C 转换所做的是尝试不同的转换(dynamic_cast 除外,并且还允许转换为无法使用的基类)并使用第一个有效的转换。我会说 C 转换和隐式转换一样强大。

      函数调用语法的显式转换:

      f(B(a));
      

      在行为上等同于 C-casting。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-23
        • 2017-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-27
        • 1970-01-01
        • 2012-03-16
        相关资源
        最近更新 更多