【问题标题】:casting comparison between Objective-C and C++Objective-C 和 C++ 之间的转换比较
【发布时间】:2011-03-09 23:55:03
【问题描述】:

好的,所以这可能是一个学术问题。有人可以告诉我 C++ 的强制转换运算符是否/如何转换为 Objective-C ......或者它们如何/为什么没有必要?

我已经脱离 C++ 循环好几年了,似乎每次我转身时他们都会添加一些新的关键字。最近向我介绍了 C++ 的各种转换运算符 reinterpret_cast、static_cast、dynamic_cast 和 const_cast。我不太清楚什么时候出现你需要使用所有这些类型的演员表的情况。

我已经使用Objective-C 一两年了,感觉还不错。 (在此之前主要是 C 人)。我试图理解为什么 C++ 似乎具有所有这些复杂性。或者换一种说法,Objective-C 缺少什么似乎没有(或不需要?)这么多的转换类型?

【问题讨论】:

  • static_cast 等已经在 C++98 中标准化,现在已经 12 年了...

标签: c++ objective-c casting


【解决方案1】:

请参阅this answer to the question When should static_cast, dynamic_cast and reinterpret_cast be used? 了解每种类型转换的含义。

Objective-C 缺少什么,它似乎没有(或不需要?)这么多的转换类型?

C++ 比 C 更关注类型安全。The many cast operators are added to make the many different casting intentions clear(并且由于其丑陋的形式而阻止人们使用它)。而且,

  • Objective-C 中没有 const 对象 (const NSObject*),其他 const 参数不像 C++ 那样强调,所以 const_cast 没用。

  • Objective-C 实例总是使用动态类型,所以不需要dynamic_cast。 (ObjC 中的类型检查通常使用-isKindOfClass: 完成。)

  • static_castreinterpret_cast 在 C 中是相同的,但在 C++ 中则不同。因为 C++ 支持多重继承(ObjC 中没有),所以指针转换不像无操作那么简单:

    #include <cstdio>
    
    struct A {
        int x;
        A() : x(12) {}
    };
    struct B {
        int y;
        B() : y(33) {}
        int get() const { return y; }
    };
    struct C : A, B {
        int z;
        C() : A(), B(), z(41) {}
    };
    
    int main () {
        C* c = new C;
        printf("%d\n", c->get());                       // 33
        printf("%d\n", static_cast<B*>(c)->get());      // 33
        printf("%d\n", reinterpret_cast<B*>(c)->get()); // 12
    }
    

【讨论】:

  • 谢谢!这是对我所看到的差异的最清楚的描述。
  • “static_cast 和 reinterpret_cast 在 C 中是一样的”?我不知道 C 有 static_castreinterpret_cast
【解决方案2】:

问题是,有几种广泛不同的类别,具有不同的意图,并且希望能够明确指定该意图,这样您就不会意外地做错事。例如,您可能将const int* 转换为const char* 以对原始字节进行操作,并且无意中也删除了const。因此,在 C++ 中,将指针从一种不相关类型更改为另一种类型是使用 reinterpret_cast 完成的,而丢弃 const 只能使用 const_cast 完成。如果你尝试const void* p; reinterpret_cast&lt;char*&gt;(p),你会得到一个错误。

dynamic_cast 需要可靠地向下转换(通过运行时检查),也需要用于交叉转换(即给定一个 Base1* 类型的指针,指向实际类型为 Derived 的对象,该对象继承自 @987654330 @ 和 Base2*,以便能够直接转换为 Base2*;对于引用也是如此 - 这对于“接口”特别有用)。

static_cast 是它的其余部分 - 值转换(intfloat 等),对象指针/引用的向上转换,以及未经检查的向下转换。它也是最常用的一种,尽管一些样式指南要求在所有对象指针/引用转换上尽可能使用dynamic_cast

一般来说,基本原理似乎是:两个最危险的操作(转换为指向不相关类型的指针和丢弃常量)都提供了它们自己的专用转换运算符,以防止它们意外发生的任何可能性。之后,为转换需要运行时查找的情况提供了一个新的运算符。最后,提供了另一个新的运算符来覆盖任何剩余的地面。旧的 C 风格“通用”强制转换运算符已被有效弃用。

现在说说为什么 Obj-C 不“需要”它们。可以说,它实际上可以使用const_castreinterpret_caststatic_cast 之间的差异——但显然,这些差异被视为没有增加足够的价值来扩展核心 C 语言。它不需要dynamic_cast,因为它没有多重继承(协议有些不同),而是通过isa 方法完成类型检查。

【讨论】:

    【解决方案3】:

    C(和 Objective C)铸件是重型橡胶木槌,而 C++ 铸件是一组凿子。它们允许您声明您想要制作的特定类型的演员表,并让编译器帮助您仅强制执行该特定类型的演员表。由于强制转换可能很危险,因此每种强制转换的有限范围使它们更安全——更笨拙的语法被吹捧为一种优势,因为它可以防止过度使用强制转换。

    与Objective C完全不同的是dynamic_cast,它会在转换为对象之前进行额外的运行时检查以确保对象是所需的类型,如果不存在则返回0或抛出异常.它类似于在进行 Objective C 转换之前在 NSObject 上调用 isKindOfClass,并且在 C++ 世界中对于向下转换非常有用。但是请注意,由于 Objective C 中的动态方法分派,您不必向下转换一个对象,然后就可以向它发送针对其类型的特定消息,因此向下转换的作用比在 C++ 世界中要少。

    【讨论】:

      【解决方案4】:

      查看the article on CPlusPlus.com,它详细描述了各种类型转换方法。

      1. reinterpret_cast 将任何指针类型转换为任何其他指针类型,甚至是不相关的类。运算结果是从一个指针到另一个指针的值的简单二进制副本。允许所有指针转换:既不检查指向的内容,也不检查指针类型本身。
      2. static_cast 可以在指向相关类的指针之间进行转换,不仅可以从派生类到其基类,还可以从基类到其派生类。这确保了如果转换了正确的对象,至少类是兼容的,但在运行时不执行安全检查来检查正在转换的对象是否实际上是目标类型的完整对象。
      3. dynamic_cast 只能用于指针和对象引用。其目的是确保类型转换的结果是所请求类的有效完整对象。
      4. const_cast 是一种类型转换,它操纵对象的常量性,无论是设置还是删除。例如,为了将 const 参数传递给需要非常量参数的函数

      从广义上讲,它们允许程序员声明他们的意图并准确地断言他们试图通过强制转换实现的目标。它们还有助于在编译时标记转换错误,否则只会在运行时出现(如果你幸运的话!)。

      我自己没有使用过 Objective C,所以我无法评论为什么该语言可能没有它们。

      【讨论】:

      • 关于reinterpret_cast 的一些更正:它只包括指向对象的指针,而不是指向函数的指针;它还允许从指针转换为整数类型并返回;并且结果是严格实现定义的,不一定是二进制副本(这并不总是可能的,因为不同类型的指针大小甚至不需要相同) - 唯一的保证是来回转换总是给出原始值,只要往返类型有足够的宽度来存储它。
      • static_cast 不能用于从虚拟基类到派生的向下转换,您必须在那里坚持使用dynamic_cast。后者还可以跨(而不是向上/向下)层次结构进行强制转换。另一方面,在某些情况下dynamic_cast 会失败,但static_cast 会起作用(重复碱基)。
      • @Jon:我宁愿让人们参考标准的文本;)
      • @Pavel:你有相关章节的链接吗?
      • 谢谢,但我能够自己查找定义。我无法理解的是它们具体如何与 Objective-C 相关(或不相关)。
      猜你喜欢
      • 2013-05-08
      • 2018-05-17
      • 2010-10-05
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      相关资源
      最近更新 更多