Objective-C和C++有何不同?

182

在语法、特性、范式、框架和库方面,Objective-C和C++有哪些主要区别?

*重要提示:我的目标不是引发两种语言之间的性能之争。我只想了解真正的硬性事实。实际上,我的问题与性能无关!请为任何可能看似主观的内容提供来源。


2
这个指南给出了我看过的最好的比较。链接 - LiraNuna
@Oskar Kjellin:Mac和LiraNuna的答案都非常出色。我无法客观地决定哪一个是最好的,因为它们互相补充。 - Alerty
@Alerty 嗯,我知道(我自己也经常遇到这种情况)。也许当我无法决定时,只需将顶部的问题标记为已回答即可。当有问题未标记为已回答时,我不喜欢这种情况 :( - Oskar Kjellin
2
将第二个答案的链接放在第一个答案中,反之亦然。 - Lee Taylor
7个回答

197

以下是一些重要的差异:

  • C++允许多重继承,而Objective-C不允许。
  • 与C++不同的是,Objective-C允许对方法参数进行命名,并且方法签名仅包含参数和返回类型的名称和类型(详见bbum和Chuck的评论)。相比之下,C++成员函数签名包含函数名称以及参数/返回类型(不包含它们的名称)。
  • C++使用booltruefalse,而Objective-C使用BOOLYESNO
  • C++使用void*nullptr,而Objective-C更喜欢使用idnil
  • Objective-C使用"选择器"(类型为SEL)作为函数指针的近似等价物。
  • Objective-C使用消息传递范式(类似于Smalltalk),您可以通过方法/选择器向对象发送"消息"。
  • Objective-C可以让您向nil发送消息,而C++如果您尝试调用nullptr的成员函数则会崩溃。
  • Objective-C允许动态派发,允许在运行时确定响应消息的类,而C++需要在编译时知道调用方法的对象(请参见wilhelmtell的评论)。这与前一点有关。
  • Objective-C允许使用"属性"自动生成成员变量的访问器。
  • Objective-C允许将值分配给self,并且允许类初始化器(类似于构造函数)在需要时返回完全不同的类。相比之下,在C++中,如果您创建了一个类的新实例(无论是隐式地在堆栈上还是通过new显式创建),它保证是您最初指定的类型。
  • 同样,在Objective-C中,其他类也可以动态地更改目标类以拦截方法调用。
  • Objective-C缺少C++的命名空间功能。
  • Objective-C缺乏C++引用的等效物。
  • Objective-C缺少模板,更倾向于(例如)在容器中允许弱类型。
  • Objective-C不允许隐式方法重载,但C++可以。也就是说,在C ++中,int foo(void)int foo(int)定义了方法foo的隐式重载,但要在Objective-C中实现相同的功能需要显式重载 - (int)foo - (int)foo:(int)intParam 。这是由于Objective-C的命名参数在功能上与C ++的名称修饰等效。
  • Objective-C很高兴让方法和变量共享相同的名称,而C ++通常会产生问题。我想这与Objective-C使用选择器而不是函数指针有关,因此方法名称实际上没有“值”。
  • Objective-C不允许在堆栈上创建对象-所有对象都必须从堆中分配(可以通过alloc消息显式分配,或者在适当的工厂方法中隐式分配)。
  • 与C ++一样,Objective-C具有结构体和类。但是,在C ++中,它们几乎完全被视为相同的内容,而在Objective-C中,则被处理方式迥异-例如,您可以在栈上创建结构体。
  • 我认为最大的区别可能是语法。您可以在任一语言中实现基本相同的功能,但在我的看法中,C ++语法更简单,而Objective-C的某些特性(例如动态调度)使得某些任务(如GUI设计)更容易。

    也许还有其他一些我忽略了的事情,如果我想到任何其他事情,我会更新。除此之外,我强烈推荐LiraNuna为您指出的指南。顺便说一句,另一个感兴趣的网站可能是这个

    我还需要指出,我自己也刚开始学习Objective-C,因此上述内容可能不太正确或完整 - 如果情况是这样的,我很抱歉,并欢迎提出改进建议。

    编辑:根据以下评论提出的要点更新,添加了几个项目到列表中。


    9
    不错的列表,一个更正。它们不是“命名参数”,而是“交错参数”。 命名和“关键字参数”会导致误解,认为某个方法名称的子集可以省略。 但实际上不能省略。 - bbum
    7
    您忘记提及最重要的区别了:Objective-C使用动态分派,而C++使用静态分派。换句话说,由Objective-C编译器编译的代码将在运行时确定负责响应消息的类;而由C++编译器编译的代码则在编译时计算并编译进去。 - wilhelmtell
    9
    C++编译器只在编译时知道超类。运行时实际的类可以是任何后代类。这也是一种动态分派形式,但不同于Objective C中使用的形式。请注意这些技术术语! - Norman Ramsey
    5
    好的清单。然而,Objective-C也使用void*NULL,但并非用于对象。在Obj-C中,您可以使用任何C风格的指针,并且许多API调用实际上通过引用传递或返回值,在这种情况下经常使用NULL - Quinn Taylor
    3
    1)C++也可以使用命名参数。请参见http://cpp-netlib.github.com/0.9.1/reference_http_server.html#constructor,其中提供了一个示例。2)通常情况下,在C ++中调用空指针上的方法不一定会导致段错误。当您访问成员变量时,大多数实现会出现段错误。 - Paul Fultz II
    显示剩余12条评论

    36

    尽管它们都源于C语言,但它们是两种完全不同的语言。

    一个主要区别是Objective-C侧重于运行时决策以进行派发,并且在继承和多态性方面严重依赖其运行时库,而在C++中通常侧重于静态、编译时的决策。

    关于库,你可以在这两种语言中使用纯C库——但它们的本地库完全不同。

    有趣的是,你可以混合使用两种语言(有一些限制)。结果被称为Objective-C++


    更新后的链接:Objective-C++ - IcyIcicle

    7

    就我所知:

    1. 样式 - Obj-C是动态的,C++通常是静态的
    2. 尽管它们都是面向对象的,但我确信解决方案会有所不同。
    3. 不同的对象模型(C++受其编译时类型系统的限制)。

    对我来说,最大的区别是模型系统。Obj-C允许您进行消息传递和内省,但C++具有强大的模板。

    每个都有其优点。


    6

    它们完全不同。Objective-C与Smalltalk比与C++更有共同点(嗯,除了语法之外)。


    5
    正如其他人所说,Objective-C在对象的思考方式上比C++更加动态。
    Objective-C是面向对象语言Smalltalk系列中的一种,其对象概念与Java、Python和其他“标准”的非C++面向对象语言非常相似。有大量的动态分派,没有运算符重载,发送消息等。
    C++则是一种奇怪的动物;它主要跳过了Smalltalk家族树的部分。在某些方面,它具有良好的模块系统,并支持继承,这可以用于面向对象编程。事情更加静态(例如,可重写的方法不是默认值)。

    4

    Objective-C是C的一个更完美的超集。在C和Objective-C中,允许从 void* 隐式转换为结构体指针。

    Foo* bar = malloc(sizeof(Foo));
    

    如果不明确转换,C++ 将无法编译 void 指针:

    Foo* bar = (Foo*)malloc(sizeof(Foo));
    

    这与日常编程无关,只是一个有趣的小知识。

    1
    第二个例子不是C++代码。它是C代码,当您尝试使用C++编译器编译它时会出现错误。如果您想要与原始代码尽可能接近的旧版C ++,则应编写Foo* bar = reinterpret_cast< Foo* >(malloc(sizeof(Foo));,然后可能使用就地构造函数。但是,从今天开始,现代C ++更像是auto bar = new Foo(constructorArg);实际上您不需要malloc,也不需要callic,您可以使用std::vector::reservestd::vector::emplace_mack - xakepp35

    2

    Obj-C在语言本身具有更多的动态能力,而C++更专注于编译时能力并具有一些动态能力。

    在C++中,参数化多态性在编译时进行检查,而在Obj-C中,参数化多态性是通过动态调度实现的,不会在编译时进行检查。

    Obj-C非常具有动态性。您可以在运行时向类中添加方法。此外,它在运行时具有内省功能以查看类。在C++中,类的定义无法更改,并且必须在编译时完成所有内省。尽管可以使用函数映射(或类似内容)在C++中实现Obj-C的动态特性,但它仍比Obj-C更冗长。

    在C++中,可以进行更多的编译时检查。例如,使用变体类型(如联合),编译器可以强制执行所有情况的编写或处理。因此,您不会忘记处理问题的边缘情况。但是,所有这些检查都会在编译时付出代价。Obj-C的编译速度比C++快得多。


    3
    如果你要谈论价格,就要公平!相反,Obj-C在运行时解析动态方法调用方面比C ++慢得多。我认为与运行速度相比,编译速度是一个相对不重要的问题。我相信由于其更具动态分派特性,Obj-C提供了许多好处,但这里存在一种权衡。 - underscore_d
    1
    确实,运行时与编译时成本之间存在权衡。然而,编译时间并非总是微不足道的。在C++中使用重型元编程和EDSL库(例如Boost.Spirit)可能会对编译时间产生巨大影响,同时在运行时生成非常快速的代码。 - Paul Fultz II
    1
    当然,相对于简单的代码库而言,我过于简化了... 对于非常复杂的代码库,重新编译以测试小的更改可能会使开发非常繁琐,这并不是一个微不足道的问题。但是我们真的可以在两者之间进行比较吗?这样依赖于C++编译时特性的库,能否以某种方式重新想象为Objective-C并显示更快的编译速度?即,"Obj-C编译速度比C++快得多"这个说法是否指的是可以测量可复制加速的等效代码库?否则,我们就在比较种植苹果和橙子所需的时间。 - underscore_d

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